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 | declare(strict_types=1); |
||
3 | |||
4 | namespace Genkgo\Mail\Mime; |
||
5 | |||
6 | use Genkgo\Mail\GenericMessage; |
||
7 | use Genkgo\Mail\Header\ContentType; |
||
8 | use Genkgo\Mail\Header\ParsedHeader; |
||
9 | use Genkgo\Mail\Header\HeaderValueParameter; |
||
10 | use Genkgo\Mail\HeaderInterface; |
||
11 | use Genkgo\Mail\MessageInterface; |
||
12 | use Genkgo\Mail\Stream\EmptyStream; |
||
13 | use Genkgo\Mail\Stream\LineIterator; |
||
14 | use Genkgo\Mail\StreamInterface; |
||
15 | |||
16 | final class MultiPart implements MultiPartInterface |
||
17 | { |
||
18 | /** |
||
19 | * @var PartInterface |
||
20 | */ |
||
21 | private $decoratedPart; |
||
22 | |||
23 | /** |
||
24 | * @var Boundary |
||
25 | */ |
||
26 | private $boundary; |
||
27 | |||
28 | /** |
||
29 | * @var array|PartInterface[] |
||
30 | */ |
||
31 | private $parts = []; |
||
32 | |||
33 | /** |
||
34 | * @param Boundary $boundary |
||
35 | * @param ContentType $contentType |
||
36 | */ |
||
37 | 30 | public function __construct(Boundary $boundary, ContentType $contentType) |
|
38 | { |
||
39 | 30 | $this->boundary = $boundary; |
|
40 | |||
41 | 30 | if (\substr((string)$contentType->getValue(), 0, 10) !== 'multipart/') { |
|
42 | 1 | throw new \InvalidArgumentException('Content type must be of type multipart/type'); |
|
43 | } |
||
44 | |||
45 | 29 | $this->decoratedPart = (new GenericPart()) |
|
46 | 29 | ->withHeader( |
|
47 | 29 | new ParsedHeader( |
|
48 | 29 | $contentType->getName(), |
|
49 | 29 | $contentType->getValue() |
|
50 | 29 | ->withParameter( |
|
51 | 29 | new HeaderValueParameter( |
|
52 | 29 | 'boundary', |
|
53 | 29 | (string)$boundary |
|
54 | ) |
||
55 | ) |
||
56 | ) |
||
57 | ); |
||
58 | 29 | } |
|
59 | |||
60 | /** |
||
61 | * @return iterable<HeaderInterface> |
||
0 ignored issues
–
show
|
|||
62 | */ |
||
63 | 17 | public function getHeaders(): iterable |
|
64 | { |
||
65 | 17 | return $this->decoratedPart->getHeaders(); |
|
66 | } |
||
67 | |||
68 | /** |
||
69 | * @param string $name |
||
70 | * @return bool |
||
71 | */ |
||
72 | 3 | public function hasHeader(string $name): bool |
|
73 | { |
||
74 | 3 | return $this->decoratedPart->hasHeader($name); |
|
75 | } |
||
76 | |||
77 | /** |
||
78 | * @param string $name |
||
79 | * @return HeaderInterface |
||
80 | */ |
||
81 | 20 | public function getHeader(string $name): HeaderInterface |
|
82 | { |
||
83 | 20 | return $this->decoratedPart->getHeader($name); |
|
84 | } |
||
85 | |||
86 | /** |
||
87 | * @param HeaderInterface $header |
||
88 | * @return PartInterface |
||
89 | */ |
||
90 | 1 | public function withHeader(HeaderInterface $header): PartInterface |
|
91 | { |
||
92 | 1 | throw new \RuntimeException('Cannot modify headers of MultiPart'); |
|
93 | } |
||
94 | |||
95 | /** |
||
96 | * @param string $name |
||
97 | * @return PartInterface |
||
98 | */ |
||
99 | 1 | public function withoutHeader(string $name): PartInterface |
|
100 | { |
||
101 | 1 | throw new \RuntimeException('Cannot modify headers of MultiPart'); |
|
102 | } |
||
103 | |||
104 | /** |
||
105 | * @param StreamInterface $body |
||
106 | * @return PartInterface |
||
107 | */ |
||
108 | 1 | public function withBody(StreamInterface $body): PartInterface |
|
109 | { |
||
110 | 1 | throw new \RuntimeException('Cannot modify body of MultiPart'); |
|
111 | } |
||
112 | |||
113 | /** |
||
114 | * @return StreamInterface |
||
115 | */ |
||
116 | 16 | public function getBody(): StreamInterface |
|
117 | { |
||
118 | 16 | return new EmptyStream(); |
|
119 | } |
||
120 | |||
121 | /** |
||
122 | * @return Boundary |
||
123 | */ |
||
124 | 18 | public function getBoundary(): Boundary |
|
125 | { |
||
126 | 18 | return $this->boundary; |
|
127 | } |
||
128 | |||
129 | /** |
||
130 | * @param PartInterface $part |
||
131 | * @return MultiPartInterface |
||
132 | */ |
||
133 | 17 | public function withPart(PartInterface $part): MultiPartInterface |
|
134 | { |
||
135 | 17 | $clone = clone $this; |
|
136 | 17 | $clone->parts[] = $part; |
|
137 | 17 | return $clone; |
|
138 | } |
||
139 | |||
140 | /** |
||
141 | * @param iterable|PartInterface[] $parts |
||
142 | * @return MultiPartInterface |
||
143 | */ |
||
144 | 7 | public function withParts(iterable $parts): MultiPartInterface |
|
145 | { |
||
146 | 7 | $clone = clone $this; |
|
147 | |||
148 | 7 | foreach ($parts as $part) { |
|
149 | 7 | $clone->parts[] = $part; |
|
150 | } |
||
151 | |||
152 | 7 | return $clone; |
|
153 | } |
||
154 | |||
155 | /** |
||
156 | * @return iterable|PartInterface[] |
||
157 | */ |
||
158 | 24 | public function getParts(): iterable |
|
159 | { |
||
160 | 24 | return $this->parts; |
|
0 ignored issues
–
show
The return type of
return $this->parts; (array ) is incompatible with the return type declared by the interface Genkgo\Mail\Mime\MultiPartInterface::getParts of type Genkgo\Mail\Mime\iterabl...il\Mime\PartInterface[] .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
161 | } |
||
162 | |||
163 | /** |
||
164 | * @param MessageInterface $message |
||
165 | * @return MultiPart |
||
166 | */ |
||
167 | 22 | public static function fromMessage(MessageInterface $message): self |
|
168 | { |
||
169 | 22 | foreach ($message->getHeader('Content-Type') as $header) { |
|
170 | 22 | $contentType = $header->getValue()->getRaw(); |
|
171 | 22 | if (\substr($contentType, 0, 10) !== 'multipart/') { |
|
172 | 22 | throw new \InvalidArgumentException( |
|
173 | 22 | \sprintf( |
|
174 | 22 | 'Message is not a multipart/alternative message, but %s', |
|
175 | 22 | $contentType |
|
176 | ) |
||
177 | ); |
||
178 | } |
||
179 | |||
180 | try { |
||
181 | 18 | $boundary = new Boundary($header->getValue()->getParameter('boundary')->getValue()); |
|
182 | } catch (\UnexpectedValueException $e) { |
||
183 | throw new \InvalidArgumentException('Message does not contain a boundary'); |
||
184 | } |
||
185 | |||
186 | 18 | $part = new self( |
|
187 | 18 | $boundary, |
|
188 | 18 | new ContentType($header->getValue()->getRaw()) |
|
189 | ); |
||
190 | |||
191 | 18 | $content = ''; |
|
192 | 18 | $preamble = true; |
|
193 | 18 | foreach (new LineIterator($message->getBody()) as $line) { |
|
194 | 18 | if ($boundary->isOpening($line) && $preamble) { |
|
195 | 18 | $content = ''; |
|
196 | 18 | $preamble = false; |
|
197 | 18 | continue; |
|
198 | } |
||
199 | |||
200 | 18 | if ($boundary->isClosing($line) || $boundary->isOpening($line)) { |
|
201 | 18 | $message = GenericMessage::fromString(\rtrim($content)); |
|
202 | |||
203 | try { |
||
204 | 18 | $part->parts[] = MultiPart::fromMessage($message); |
|
205 | 18 | } catch (\InvalidArgumentException $e) { |
|
206 | 18 | $part->parts[] = GenericPart::fromMessage($message); |
|
207 | } |
||
208 | |||
209 | 18 | $content = ''; |
|
210 | } |
||
211 | |||
212 | 18 | if ($boundary->isOpening($line)) { |
|
213 | 18 | continue; |
|
214 | } |
||
215 | |||
216 | 18 | if ($boundary->isClosing($line)) { |
|
217 | 18 | break; |
|
218 | } |
||
219 | |||
220 | 18 | $content .= $line . "\r\n"; |
|
221 | } |
||
222 | |||
223 | 18 | return $part; |
|
224 | } |
||
225 | |||
226 | throw new \InvalidArgumentException('Message is not a multipart/alternative message'); |
||
227 | } |
||
228 | } |
||
229 |
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.