1 | <?php |
||||||
2 | /** |
||||||
3 | * This file is part of the ZBateson\MailMimeParser project. |
||||||
4 | * |
||||||
5 | * @license http://opensource.org/licenses/bsd-license.php BSD |
||||||
6 | */ |
||||||
7 | |||||||
8 | namespace ZBateson\MailMimeParser\Message\Helper; |
||||||
9 | |||||||
10 | use Psr\Http\Message\StreamInterface; |
||||||
11 | use ZBateson\MailMimeParser\Header\HeaderConsts; |
||||||
12 | use ZBateson\MailMimeParser\IMessage; |
||||||
13 | use ZBateson\MailMimeParser\Message\Factory\IMimePartFactory; |
||||||
14 | use ZBateson\MailMimeParser\Message\Factory\IUUEncodedPartFactory; |
||||||
15 | use ZBateson\MailMimeParser\Message\IMessagePart; |
||||||
16 | |||||||
17 | /** |
||||||
18 | * Provides routines to set or retrieve the signature part of a signed message. |
||||||
19 | * |
||||||
20 | * @author Zaahid Bateson |
||||||
21 | */ |
||||||
22 | class PrivacyHelper extends AbstractHelper |
||||||
23 | { |
||||||
24 | /** |
||||||
25 | * @var GenericHelper a GenericHelper instance |
||||||
26 | */ |
||||||
27 | private GenericHelper $genericHelper; |
||||||
28 | |||||||
29 | /** |
||||||
30 | * @var MultipartHelper a MultipartHelper instance |
||||||
31 | */ |
||||||
32 | private MultipartHelper $multipartHelper; |
||||||
33 | |||||||
34 | 7 | public function __construct( |
|||||
35 | IMimePartFactory $mimePartFactory, |
||||||
36 | IUUEncodedPartFactory $uuEncodedPartFactory, |
||||||
37 | GenericHelper $genericHelper, |
||||||
38 | MultipartHelper $multipartHelper |
||||||
39 | ) { |
||||||
40 | 7 | parent::__construct($mimePartFactory, $uuEncodedPartFactory); |
|||||
41 | 7 | $this->genericHelper = $genericHelper; |
|||||
42 | 7 | $this->multipartHelper = $multipartHelper; |
|||||
43 | } |
||||||
44 | |||||||
45 | /** |
||||||
46 | * The passed message is set as multipart/signed, and a new part is created |
||||||
47 | * below it with content headers, content and children copied from the |
||||||
48 | * message. |
||||||
49 | * |
||||||
50 | * @param string $micalg |
||||||
51 | * @param string $protocol |
||||||
52 | */ |
||||||
53 | 10 | public function setMessageAsMultipartSigned(IMessage $message, $micalg, $protocol) : static |
|||||
54 | { |
||||||
55 | 10 | if (\strcasecmp($message->getContentType(), 'multipart/signed') !== 0) { |
|||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
56 | 10 | $this->multipartHelper->enforceMime($message); |
|||||
57 | 10 | $messagePart = $this->mimePartFactory->newInstance(); |
|||||
58 | 10 | $this->genericHelper->movePartContentAndChildren($message, $messagePart); |
|||||
59 | 10 | $message->addChild($messagePart); |
|||||
60 | 10 | $boundary = $this->multipartHelper->getUniqueBoundary('multipart/signed'); |
|||||
61 | 10 | $message->setRawHeader( |
|||||
62 | 10 | HeaderConsts::CONTENT_TYPE, |
|||||
63 | 10 | "multipart/signed;\r\n\tboundary=\"$boundary\";\r\n\tmicalg=\"$micalg\"; protocol=\"$protocol\"" |
|||||
64 | 10 | ); |
|||||
65 | } |
||||||
66 | 10 | $this->overwrite8bitContentEncoding($message); |
|||||
67 | 10 | $this->setSignature($message, 'Empty'); |
|||||
68 | 10 | return $this; |
|||||
69 | } |
||||||
70 | |||||||
71 | /** |
||||||
72 | * Sets the signature of the message to $body, creating a signature part if |
||||||
73 | * one doesn't exist. |
||||||
74 | * |
||||||
75 | * @param string $body |
||||||
76 | */ |
||||||
77 | 11 | public function setSignature(IMessage $message, $body) : static |
|||||
78 | { |
||||||
79 | 11 | $signedPart = $message->getSignaturePart(); |
|||||
80 | 11 | if ($signedPart === null) { |
|||||
81 | 10 | $signedPart = $this->mimePartFactory->newInstance(); |
|||||
82 | 10 | $message->addChild($signedPart); |
|||||
83 | } |
||||||
84 | 11 | $signedPart->setRawHeader( |
|||||
0 ignored issues
–
show
The method
setRawHeader() does not exist on ZBateson\MailMimeParser\Message\IMessagePart . It seems like you code against a sub-type of ZBateson\MailMimeParser\Message\IMessagePart such as ZBateson\MailMimeParser\Message\MimePart or ZBateson\MailMimeParser\Message\IMimePart or ZBateson\MailMimeParser\Message\MimePart .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
85 | 11 | HeaderConsts::CONTENT_TYPE, |
|||||
86 | 11 | $message->getHeaderParameter(HeaderConsts::CONTENT_TYPE, 'protocol') |
|||||
87 | 11 | ); |
|||||
88 | 11 | $signedPart->setContent($body); |
|||||
89 | 11 | return $this; |
|||||
90 | } |
||||||
91 | |||||||
92 | /** |
||||||
93 | * Loops over parts of the message and sets the content-transfer-encoding |
||||||
94 | * header to quoted-printable for text/* mime parts, and to base64 |
||||||
95 | * otherwise for parts that are '8bit' encoded. |
||||||
96 | * |
||||||
97 | * Used for multipart/signed messages which doesn't support 8bit transfer |
||||||
98 | * encodings. |
||||||
99 | */ |
||||||
100 | 11 | public function overwrite8bitContentEncoding(IMessage $message) : static |
|||||
101 | { |
||||||
102 | 11 | $parts = $message->getAllParts(function(IMessagePart $part) { |
|||||
0 ignored issues
–
show
|
|||||||
103 | 9 | return \strcasecmp($part->getContentTransferEncoding(), '8bit') === 0; |
|||||
0 ignored issues
–
show
It seems like
$part->getContentTransferEncoding() can also be of type null ; however, parameter $string1 of strcasecmp() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
104 | 11 | }); |
|||||
105 | 11 | foreach ($parts as $part) { |
|||||
106 | 3 | $contentType = \strtolower($part->getContentType()); |
|||||
0 ignored issues
–
show
It seems like
$part->getContentType() can also be of type null ; however, parameter $string of strtolower() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
107 | 3 | $part->setRawHeader( |
|||||
108 | 3 | HeaderConsts::CONTENT_TRANSFER_ENCODING, |
|||||
109 | 3 | ($contentType === 'text/plain' || $contentType === 'text/html') ? |
|||||
110 | 2 | 'quoted-printable' : |
|||||
111 | 3 | 'base64' |
|||||
112 | 3 | ); |
|||||
113 | } |
||||||
114 | 11 | return $this; |
|||||
115 | } |
||||||
116 | |||||||
117 | /** |
||||||
118 | * Returns a stream that can be used to read the content part of a signed |
||||||
119 | * message, which can be used to sign an email or verify a signature. |
||||||
120 | * |
||||||
121 | * The method simply returns the stream for the first child. No |
||||||
122 | * verification of whether the message is in fact a signed message is |
||||||
123 | * performed. |
||||||
124 | * |
||||||
125 | * Note that unlike getSignedMessageAsString, getSignedMessageStream doesn't |
||||||
126 | * replace new lines. |
||||||
127 | * |
||||||
128 | * @return ?StreamInterface null if the message doesn't have any children |
||||||
129 | */ |
||||||
130 | 16 | public function getSignedMessageStream(IMessage $message) : ?StreamInterface |
|||||
131 | { |
||||||
132 | 16 | $child = $message->getChild(0); |
|||||
133 | 16 | if ($child !== null) { |
|||||
134 | 16 | return $child->getStream(); |
|||||
135 | } |
||||||
136 | 2 | return null; |
|||||
137 | } |
||||||
138 | |||||||
139 | /** |
||||||
140 | * Returns a string containing the entire body (content) of a signed message |
||||||
141 | * for verification or calculating a signature. |
||||||
142 | * |
||||||
143 | * Non-CRLF new lines are replaced to always be CRLF. |
||||||
144 | * |
||||||
145 | * @return ?string null if the message doesn't have any children |
||||||
146 | */ |
||||||
147 | 15 | public function getSignedMessageAsString(IMessage $message) : ?string |
|||||
148 | { |
||||||
149 | 15 | $stream = $this->getSignedMessageStream($message); |
|||||
150 | 15 | if ($stream !== null) { |
|||||
151 | 15 | return \preg_replace( |
|||||
152 | 15 | '/\r\n|\r|\n/', |
|||||
153 | 15 | "\r\n", |
|||||
154 | 15 | $stream->getContents() |
|||||
155 | 15 | ); |
|||||
156 | } |
||||||
157 | 1 | return null; |
|||||
158 | } |
||||||
159 | } |
||||||
160 |