Test Failed
Push — master ( 655c99...190cd0 )
by Zaahid
03:30 queued 13s
created

PrivacyHelper   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 13
eloc 45
c 2
b 0
f 0
dl 0
loc 135
ccs 54
cts 54
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getSignedMessageAsString() 0 11 2
A overwrite8bitContentEncoding() 0 12 4
A getSignedMessageStream() 0 7 2
A setSignature() 0 12 2
A setMessageAsMultipartSigned() 0 15 2
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 ZBateson\MailMimeParser\Header\HeaderConsts;
11
use ZBateson\MailMimeParser\IMessage;
12
use ZBateson\MailMimeParser\Message\Factory\IMimePartFactory;
13
use ZBateson\MailMimeParser\Message\Factory\IUUEncodedPartFactory;
14
use ZBateson\MailMimeParser\Message\IMessagePart;
15
16
/**
17
 * Provides routines to set or retrieve the signature part of a signed message.
18
 *
19
 * @author Zaahid Bateson
20
 */
21
class PrivacyHelper extends AbstractHelper
22
{
23
    /**
24
     * @var GenericHelper a GenericHelper instance
25
     */
26
    private $genericHelper;
27
28
    /**
29
     * @var MultipartHelper a MultipartHelper instance
30
     */
31
    private $multipartHelper;
32
33 7
    public function __construct(
34
        IMimePartFactory $mimePartFactory,
35
        IUUEncodedPartFactory $uuEncodedPartFactory,
36
        GenericHelper $genericHelper,
37
        MultipartHelper $multipartHelper
38
    ) {
39 7
        parent::__construct($mimePartFactory, $uuEncodedPartFactory);
40 7
        $this->genericHelper = $genericHelper;
41 7
        $this->multipartHelper = $multipartHelper;
42
    }
43
44
    /**
45
     * The passed message is set as multipart/signed, and a new part is created
46
     * below it with content headers, content and children copied from the
47
     * message.
48
     *
49
     * @param string $micalg
50
     * @param string $protocol
51
     */
52 10
    public function setMessageAsMultipartSigned(IMessage $message, $micalg, $protocol)
53
    {
54 10
        if (\strcasecmp($message->getContentType(), 'multipart/signed') !== 0) {
0 ignored issues
show
Bug introduced by
It seems like $message->getContentType() 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 ignore-type  annotation

54
        if (\strcasecmp(/** @scrutinizer ignore-type */ $message->getContentType(), 'multipart/signed') !== 0) {
Loading history...
55 10
            $this->multipartHelper->enforceMime($message);
56 10
            $messagePart = $this->mimePartFactory->newInstance();
57 10
            $this->genericHelper->movePartContentAndChildren($message, $messagePart);
58 10
            $message->addChild($messagePart);
59 10
            $boundary = $this->multipartHelper->getUniqueBoundary('multipart/signed');
60 10
            $message->setRawHeader(
61 10
                HeaderConsts::CONTENT_TYPE,
62 10
                "multipart/signed;\r\n\tboundary=\"$boundary\";\r\n\tmicalg=\"$micalg\"; protocol=\"$protocol\""
63 10
            );
64
        }
65 10
        $this->overwrite8bitContentEncoding($message);
66 10
        $this->setSignature($message, 'Empty');
67 10
    }
68
69
    /**
70
     * Sets the signature of the message to $body, creating a signature part if
71
     * one doesn't exist.
72
     *
73
     * @param string $body
74
     */
75
    public function setSignature(IMessage $message, $body)
76 11
    {
77
        $signedPart = $message->getSignaturePart();
78 11
        if ($signedPart === null) {
79 11
            $signedPart = $this->mimePartFactory->newInstance();
80 10
            $message->addChild($signedPart);
81 10
        }
82
        $signedPart->setRawHeader(
83 11
            HeaderConsts::CONTENT_TYPE,
84 11
            $message->getHeaderParameter(HeaderConsts::CONTENT_TYPE, 'protocol')
85 11
        );
86 11
        $signedPart->setContent($body);
87 11
    }
88
89
    /**
90
     * Loops over parts of the message and sets the content-transfer-encoding
91
     * header to quoted-printable for text/* mime parts, and to base64
92
     * otherwise for parts that are '8bit' encoded.
93
     *
94
     * Used for multipart/signed messages which doesn't support 8bit transfer
95
     * encodings.
96
     *
97
     */
98
    public function overwrite8bitContentEncoding(IMessage $message)
99 11
    {
100
        $parts = $message->getAllParts(function(IMessagePart $part) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
101 11
            return \strcasecmp($part->getContentTransferEncoding(), '8bit') === 0;
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

101
            return \strcasecmp(/** @scrutinizer ignore-type */ $part->getContentTransferEncoding(), '8bit') === 0;
Loading history...
102 9
        });
103 11
        foreach ($parts as $part) {
104 11
            $contentType = \strtolower($part->getContentType());
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

104
            $contentType = \strtolower(/** @scrutinizer ignore-type */ $part->getContentType());
Loading history...
105 3
            $part->setRawHeader(
0 ignored issues
show
Bug introduced by
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 ignore-call  annotation

105
            $part->/** @scrutinizer ignore-call */ 
106
                   setRawHeader(
Loading history...
106 3
                HeaderConsts::CONTENT_TRANSFER_ENCODING,
107 3
                ($contentType === 'text/plain' || $contentType === 'text/html') ?
108 3
                'quoted-printable' :
109 2
                'base64'
110 3
            );
111 3
        }
112
    }
113
114
    /**
115
     * Returns a stream that can be used to read the content part of a signed
116
     * message, which can be used to sign an email or verify a signature.
117
     *
118
     * The method simply returns the stream for the first child.  No
119
     * verification of whether the message is in fact a signed message is
120
     * performed.
121 11
     *
122
     * Note that unlike getSignedMessageAsString, getSignedMessageStream doesn't
123 11
     * replace new lines.
124 11
     *
125 6
     * @return \Psr\Http\Message\StreamInterface or null if the message doesn't
126 6
     *         have any children
127 6
     */
128 6
    public function getSignedMessageStream(IMessage $message)
129 6
    {
130 6
        $child = $message->getChild(0);
131
        if ($child !== null) {
132
            return $child->getStream();
133
        }
134
        return null;
135
    }
136
137
    /**
138
     * Returns a string containing the entire body (content) of a signed message
139
     * for verification or calculating a signature.
140
     *
141
     * Non-CRLF new lines are replaced to always be CRLF.
142
     *
143
     * @return string or null if the message doesn't have any children
144
     */
145
    public function getSignedMessageAsString(IMessage $message)
146
    {
147
        $stream = $this->getSignedMessageStream($message);
148
        if ($stream !== null) {
149 16
            return \preg_replace(
150
                '/\r\n|\r|\n/',
151 16
                "\r\n",
152 16
                $stream->getContents()
153 16
            );
154
        }
155 2
        return null;
156
    }
157
}
158