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.
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 Ddeboer\Imap\Message; |
||
4 | |||
5 | use Ddeboer\Imap\Parameters; |
||
6 | use Ddeboer\Transcoder\Transcoder; |
||
7 | |||
8 | /** |
||
9 | * A message part |
||
10 | */ |
||
11 | class Part implements \RecursiveIterator |
||
12 | { |
||
13 | const TYPE_TEXT = 'text'; |
||
14 | const TYPE_MULTIPART = 'multipart'; |
||
15 | const TYPE_MESSAGE = 'message'; |
||
16 | const TYPE_APPLICATION = 'application'; |
||
17 | const TYPE_AUDIO = 'audio'; |
||
18 | const TYPE_IMAGE = 'image'; |
||
19 | const TYPE_VIDEO = 'video'; |
||
20 | const TYPE_OTHER = 'other'; |
||
21 | const TYPE_UNKNOWN = 'unknown'; |
||
22 | |||
23 | const ENCODING_7BIT = '7bit'; |
||
24 | const ENCODING_8BIT = '8bit'; |
||
25 | const ENCODING_BINARY = 'binary'; |
||
26 | const ENCODING_BASE64 = 'base64'; |
||
27 | const ENCODING_QUOTED_PRINTABLE = 'quoted-printable'; |
||
28 | const ENCODING_UNKNOWN = 'unknown'; |
||
29 | |||
30 | const SUBTYPE_TEXT = 'TEXT'; |
||
31 | const SUBTYPE_HTML = 'HTML'; |
||
32 | |||
33 | protected $typesMap = array( |
||
34 | 0 => self::TYPE_TEXT, |
||
35 | 1 => self::TYPE_MULTIPART, |
||
36 | 2 => self::TYPE_MESSAGE, |
||
37 | 3 => self::TYPE_APPLICATION, |
||
38 | 4 => self::TYPE_AUDIO, |
||
39 | 5 => self::TYPE_IMAGE, |
||
40 | 6 => self::TYPE_VIDEO, |
||
41 | 7 => self::TYPE_OTHER |
||
42 | ); |
||
43 | |||
44 | protected $encodingsMap = array( |
||
45 | 0 => self::ENCODING_7BIT, |
||
46 | 1 => self::ENCODING_8BIT, |
||
47 | 2 => self::ENCODING_BINARY, |
||
48 | 3 => self::ENCODING_BASE64, |
||
49 | 4 => self::ENCODING_QUOTED_PRINTABLE, |
||
50 | 5 => self::ENCODING_UNKNOWN |
||
51 | ); |
||
52 | |||
53 | protected $type; |
||
54 | |||
55 | protected $subtype; |
||
56 | |||
57 | protected $encoding; |
||
58 | |||
59 | protected $bytes; |
||
60 | |||
61 | protected $lines; |
||
62 | |||
63 | /** |
||
64 | * @var Parameters |
||
65 | */ |
||
66 | protected $parameters; |
||
67 | |||
68 | protected $stream; |
||
69 | |||
70 | protected $messageNumber; |
||
71 | |||
72 | protected $partNumber; |
||
73 | |||
74 | protected $structure; |
||
75 | |||
76 | protected $content; |
||
77 | |||
78 | protected $decodedContent; |
||
79 | |||
80 | protected $parts = array(); |
||
81 | |||
82 | protected $key = 0; |
||
83 | |||
84 | protected $disposition; |
||
85 | |||
86 | /** |
||
87 | * Constructor |
||
88 | * |
||
89 | * @param resource $stream IMAP stream |
||
90 | * @param int $messageNumber Message number |
||
91 | * @param int $partNumber Part number (optional) |
||
92 | * @param \stdClass $structure Part structure |
||
93 | */ |
||
94 | public function __construct( |
||
95 | $stream, |
||
96 | $messageNumber, |
||
97 | $partNumber = null, |
||
98 | \stdClass $structure = null |
||
99 | ) { |
||
100 | $this->stream = $stream; |
||
101 | $this->messageNumber = $messageNumber; |
||
102 | $this->partNumber = $partNumber; |
||
103 | $this->structure = $structure; |
||
104 | $this->parseStructure($structure); |
||
0 ignored issues
–
show
|
|||
105 | } |
||
106 | |||
107 | public function getCharset() |
||
108 | { |
||
109 | return $this->parameters->get('charset'); |
||
110 | } |
||
111 | |||
112 | public function getType() |
||
113 | { |
||
114 | return $this->type; |
||
115 | } |
||
116 | |||
117 | public function getSubtype() |
||
118 | { |
||
119 | return $this->subtype; |
||
120 | } |
||
121 | |||
122 | public function getEncoding() |
||
123 | { |
||
124 | return $this->encoding; |
||
125 | } |
||
126 | |||
127 | public function getBytes() |
||
128 | { |
||
129 | return $this->bytes; |
||
130 | } |
||
131 | |||
132 | public function getLines() |
||
133 | { |
||
134 | return $this->lines; |
||
135 | } |
||
136 | |||
137 | public function getParameters() |
||
138 | { |
||
139 | return $this->parameters; |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get raw part content |
||
144 | * |
||
145 | * @return string |
||
146 | */ |
||
147 | public function getContent($keepUnseen = false) |
||
148 | { |
||
149 | if (null === $this->content) { |
||
150 | $this->content = $this->doGetContent($keepUnseen); |
||
151 | } |
||
152 | |||
153 | return $this->content; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Get decoded part content |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | public function getDecodedContent($keepUnseen = false) |
||
162 | { |
||
163 | if (null === $this->decodedContent) { |
||
164 | switch ($this->getEncoding()) { |
||
165 | case self::ENCODING_BASE64: |
||
166 | $this->decodedContent = base64_decode($this->getContent($keepUnseen)); |
||
167 | break; |
||
168 | case self::ENCODING_QUOTED_PRINTABLE: |
||
169 | $this->decodedContent = quoted_printable_decode($this->getContent($keepUnseen)); |
||
170 | break; |
||
171 | case self::ENCODING_7BIT: |
||
172 | case self::ENCODING_8BIT: |
||
173 | case self::ENCODING_BINARY: |
||
174 | $this->decodedContent = $this->getContent($keepUnseen); |
||
175 | break; |
||
176 | default: |
||
177 | throw new \UnexpectedValueException('Cannot decode ' . $this->getEncoding()); |
||
178 | } |
||
179 | |||
180 | // If this part is a text part, try to convert its encoding to UTF-8. |
||
181 | // We don't want to convert an attachment's encoding. |
||
182 | if ($this->getType() === self::TYPE_TEXT |
||
183 | && strtolower($this->getCharset()) != 'utf-8' |
||
184 | ) { |
||
185 | $this->decodedContent = Transcoder::create()->transcode( |
||
186 | $this->decodedContent, |
||
187 | $this->getCharset() |
||
188 | ); |
||
189 | } |
||
190 | } |
||
191 | |||
192 | return $this->decodedContent; |
||
193 | } |
||
194 | |||
195 | public function getStructure() |
||
196 | { |
||
197 | return $this->structure; |
||
198 | } |
||
199 | |||
200 | protected function fetchStructure($partNumber = null) |
||
201 | { |
||
202 | if (null === $this->structure) { |
||
203 | $this->loadStructure(); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Ddeboer\Imap\Message\Part as the method loadStructure() does only exist in the following sub-classes of Ddeboer\Imap\Message\Part : Ddeboer\Imap\Message . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
204 | } |
||
205 | |||
206 | if ($partNumber) { |
||
207 | return $this->structure->parts[$partNumber]; |
||
208 | } |
||
209 | |||
210 | return $this->structure; |
||
211 | } |
||
212 | |||
213 | protected function parseStructure(\stdClass $structure) { |
||
214 | |||
215 | if (isset($structure->type) && isset($this->typesMap[$structure->type])) { |
||
216 | $this->type = $this->typesMap[$structure->type]; |
||
217 | } else { |
||
218 | $this->type = self::TYPE_UNKNOWN; |
||
219 | } |
||
220 | |||
221 | if(isset($structure->encoding)) |
||
222 | $this->encoding = $this->encodingsMap[$structure->encoding]; |
||
223 | if(isset($structure->subtype)) |
||
224 | $this->subtype = $structure->subtype; |
||
225 | |||
226 | if (isset($structure->bytes)) { |
||
227 | $this->bytes = $structure->bytes; |
||
228 | } |
||
229 | |||
230 | foreach (array('disposition', 'bytes', 'description') as $optional) { |
||
231 | if (isset($structure->$optional)) { |
||
232 | $this->$optional = $structure->$optional; |
||
233 | } |
||
234 | } |
||
235 | |||
236 | $this->parameters = new Parameters(); |
||
237 | if(isset($structure->parameters)) |
||
238 | if (is_array($structure->parameters)) { |
||
239 | $this->parameters->add($structure->parameters); |
||
240 | } |
||
241 | |||
242 | if (isset($structure->dparameters)) { |
||
243 | $this->parameters->add($structure->dparameters); |
||
244 | } |
||
245 | |||
246 | if (isset($structure->parts)) { |
||
247 | foreach ($structure->parts as $key => $partStructure) { |
||
248 | if (null === $this->partNumber) { |
||
249 | $partNumber = ($key + 1); |
||
250 | } else { |
||
251 | $partNumber = (string) ($this->partNumber . '.' . ($key+1)); |
||
252 | } |
||
253 | |||
254 | if ($this->isAttachment($partStructure)) { |
||
255 | $this->parts[] = new Attachment($this->stream, $this->messageNumber, $partNumber, $partStructure); |
||
256 | } else { |
||
257 | $this->parts[] = new Part($this->stream, $this->messageNumber, $partNumber, $partStructure); |
||
258 | } |
||
259 | } |
||
260 | } |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Get an array of all parts for this message |
||
265 | * |
||
266 | * @return self[] |
||
267 | */ |
||
268 | public function getParts() |
||
269 | { |
||
270 | return $this->parts; |
||
271 | } |
||
272 | |||
273 | public function current() |
||
274 | { |
||
275 | return $this->parts[$this->key]; |
||
276 | } |
||
277 | |||
278 | public function getChildren() |
||
279 | { |
||
280 | return $this->current(); |
||
281 | } |
||
282 | |||
283 | public function hasChildren() |
||
284 | { |
||
285 | return count($this->parts) > 0; |
||
286 | } |
||
287 | |||
288 | public function key() |
||
289 | { |
||
290 | return $this->key; |
||
291 | } |
||
292 | |||
293 | public function next() |
||
294 | { |
||
295 | ++$this->key; |
||
296 | } |
||
297 | |||
298 | public function rewind() |
||
299 | { |
||
300 | $this->key = 0; |
||
301 | } |
||
302 | |||
303 | public function valid() |
||
304 | { |
||
305 | return isset($this->parts[$this->key]); |
||
306 | } |
||
307 | |||
308 | public function getDisposition() |
||
309 | { |
||
310 | return $this->disposition; |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * Get raw message content |
||
315 | * |
||
316 | * @param bool $keepUnseen Whether to keep the message unseen. |
||
317 | * Default behaviour is set set the seen flag when |
||
318 | * getting content. |
||
319 | * |
||
320 | * @return string |
||
321 | */ |
||
322 | protected function doGetContent($keepUnseen = false) |
||
323 | { |
||
324 | return imap_fetchbody( |
||
325 | $this->stream, |
||
326 | $this->messageNumber, |
||
327 | $this->partNumber ?: 1, |
||
328 | \FT_UID | ($keepUnseen ? \FT_PEEK : null) |
||
329 | ); |
||
330 | } |
||
331 | |||
332 | private function isAttachment($part) { |
||
333 | |||
334 | // Attachment with correct Content-Disposition header |
||
335 | if (isset($part->disposition)) { |
||
336 | if (('attachment' === strtolower($part->disposition) |
||
337 | || 'inline' === strtolower($part->disposition)) |
||
338 | && strtoupper($part->subtype) != "PLAIN" |
||
339 | ) { |
||
340 | return true; |
||
341 | } |
||
342 | } |
||
343 | |||
344 | // Attachment without Content-Disposition header |
||
345 | if (isset($part->parameters)) { |
||
346 | View Code Duplication | foreach ($part->parameters as $parameter) { |
|
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. ![]() |
|||
347 | if ('name' === strtolower($parameter->attribute) |
||
348 | || 'filename' === strtolower($parameter->attribute) |
||
349 | ) { |
||
350 | return true; |
||
351 | } |
||
352 | } |
||
353 | |||
354 | if(isset($part->dparameters)) |
||
355 | View Code Duplication | foreach ($part->dparameters as $parameter) { |
|
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. ![]() |
|||
356 | if ('name' === strtolower($parameter->attribute) |
||
357 | || 'filename' === strtolower($parameter->attribute) |
||
358 | ) { |
||
359 | return true; |
||
360 | } |
||
361 | } |
||
362 | } |
||
363 | |||
364 | return false; |
||
365 | } |
||
366 | } |
||
367 |
It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.
We recommend to add an additional type check (or disallow null for the parameter):