zbateson /
mail-mime-parser
| 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
Loading history...
|
|||||||
| 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
Loading history...
|
|||||||
| 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
Loading history...
|
|||||||
| 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
Loading history...
|
|||||||
| 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 |