Test Failed
Push — 2.0 ( 0b4092...91a8b2 )
by Zaahid
04:50
created

MimeParser::canParse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
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
namespace ZBateson\MailMimeParser\Parser;
8
9
use ZBateson\MailMimeParser\Message\PartHeaderContainer;
10
use ZBateson\MailMimeParser\Message\Factory\PartHeaderContainerFactory;
11
use ZBateson\MailMimeParser\Parser\Proxy\ParserMessageProxyFactory;
12
use ZBateson\MailMimeParser\Parser\Proxy\ParserMimePartProxyFactory;
13
use ZBateson\MailMimeParser\Parser\Proxy\ParserMimePartProxy;
14
use ZBateson\MailMimeParser\Parser\Proxy\ParserPartProxy;
15
16
/**
17
 * Reads the content of a mime part.
18
 *
19
 * @author Zaahid Bateson
20
 */
21
class MimeParser extends AbstractParser
22
{
23
    /**
24
     * @var PartBuilderFactory
25
     */
26
    protected $partBuilderFactory;
27
28
    /**
29
     * @var PartHeaderContainerFactory
30
     */
31
    protected $partHeaderContainerFactory;
32
33
    /**
34
     * @var HeaderParser
35
     */
36
    protected $headerParser;
37
38
    public function __construct(
39
        ParserMessageProxyFactory $parserMessageProxyFactory,
40
        ParserMimePartProxyFactory $parserMimePartProxyFactory,
41
        PartBuilderFactory $pbf,
42
        PartHeaderContainerFactory $phcf,
43
        HeaderParser $hp
44
    ) {
45
        parent::__construct($parserMessageProxyFactory, $parserMimePartProxyFactory);
46
        $this->partBuilderFactory = $pbf;
47
        $this->partHeaderContainerFactory = $phcf;
48
        $this->headerParser = $hp;
49
    }
50
51
    public function canParse(PartBuilder $part)
52
    {
53
        return $part->isMime();
54
    }
55
56
    /**
57
     * 
58
     * @param resource $handle
59
     * @return string
60
     */
61
    private function readBoundaryLine($handle, ParserMimePartProxy $proxy)
62
    {
63
        $size = 2048;
64
        $isCut = false;
65
        $line = fgets($handle, $size);
66
        while (strlen($line) === $size - 1 && substr($line, -1) !== "\n") {
67
            $line = fgets($handle, $size);
68
            $isCut = true;
69
        }
70
        $ret = rtrim($line, "\r\n");
71
        $proxy->setLastLineEndingLength(strlen($line) - strlen($ret));
72
        return ($isCut) ? '' : $ret;
73
    }
74
75
    /**
76
     * Reads lines from the passed $handle, calling
77
     * $partBuilder->setEndBoundaryFound with the passed line until it returns
78
     * true or the stream is at EOF.
79
     *
80
     * setEndBoundaryFound returns true if the passed line matches a boundary
81
     * for the $partBuilder itself or any of its parents.
82
     *
83
     * Once a boundary is found, setStreamPartAndContentEndPos is called with
84
     * the passed $handle's read pos before the boundary and its line separator
85
     * were read.
86
     *
87
     * @param PartBuilder $partBuilder
88
     */
89
    private function findContentBoundary(ParserMimePartProxy $proxy)
90
    {
91
        $handle = $proxy->getMessageResourceHandle();
92
        // last separator before a boundary belongs to the boundary, and is not
93
        // part of the current part
94
        while (!feof($handle)) {
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type mixed; however, parameter $stream of feof() does only seem to accept resource, 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

94
        while (!feof(/** @scrutinizer ignore-type */ $handle)) {
Loading history...
95
            $endPos = ftell($handle) - $proxy->getLastLineEndingLength();
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type mixed; however, parameter $stream of ftell() does only seem to accept resource, 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

95
            $endPos = ftell(/** @scrutinizer ignore-type */ $handle) - $proxy->getLastLineEndingLength();
Loading history...
96
            $line = $this->readBoundaryLine($handle, $proxy);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type mixed; however, parameter $handle of ZBateson\MailMimeParser\...ser::readBoundaryLine() does only seem to accept resource, 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

96
            $line = $this->readBoundaryLine(/** @scrutinizer ignore-type */ $handle, $proxy);
Loading history...
97
            if (substr($line, 0, 2) === '--' && $proxy->setEndBoundaryFound($line)) {
98
                $proxy->setStreamPartAndContentEndPos($endPos);
99
                return;
100
            }
101
        }
102
        $proxy->setStreamPartAndContentEndPos(ftell($handle));
103
        $proxy->setEof();
104
    }
105
106
    public function parseContent(ParserPartProxy $proxy)
107
    {
108
        $proxy->setStreamContentStartPos($proxy->getMessageResourceHandlePos());
109
        $this->findContentBoundary($proxy);
110
    }
111
112
    /**
113
     * Checks if the new child part is just content past the end boundary
114
     *
115
     * @param ParserProxy $proxy
0 ignored issues
show
Bug introduced by
The type ZBateson\MailMimeParser\Parser\ParserProxy was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
116
     * @param PartBuilder $parent
117
     * @param PartBuilder $child
118
     */
119
    private function createPart(PartHeaderContainer $headerContainer, PartBuilder $child)
120
    {
121
        $parentProxy = $child->getParent();
122
        if ($parentProxy === null || !$parentProxy->isEndBoundaryFound()) {
0 ignored issues
show
Bug introduced by
The method isEndBoundaryFound() does not exist on ZBateson\MailMimeParser\...r\Proxy\ParserPartProxy. It seems like you code against a sub-type of ZBateson\MailMimeParser\...r\Proxy\ParserPartProxy such as ZBateson\MailMimeParser\...oxy\ParserMimePartProxy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

122
        if ($parentProxy === null || !$parentProxy->/** @scrutinizer ignore-call */ isEndBoundaryFound()) {
Loading history...
123
            $this->headerParser->parse(
124
                $child->getMessageResourceHandle(),
0 ignored issues
show
Bug introduced by
It seems like $child->getMessageResourceHandle() can also be of type mixed; however, parameter $handle of ZBateson\MailMimeParser\...r\HeaderParser::parse() does only seem to accept resource, 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

124
                /** @scrutinizer ignore-type */ $child->getMessageResourceHandle(),
Loading history...
125
                $headerContainer
126
            );
127
            $parserProxy = $this->parserManager->createParserProxyFor($child);
128
            return $parserProxy;
129
        } else {
130
            // reads content past an end boundary if there is any
131
            $parserProxy = $this->parserPartProxyFactory->newInstance($child, $this);
132
            $this->parseContent($parserProxy);
133
            return null;
134
        }
135
    }
136
137
    /**
138
     * Returns true if there are more parts
139
     *
140
     * @param PartBuilder $partBuilder
141
     * @return ParserPartProxy
142
     */
143
    public function parseNextChild(ParserMimePartProxy $proxy)
144
    {
145
        if ($proxy->isParentBoundaryFound()) {
146
            return null;
147
        }
148
        $headerContainer = $this->partHeaderContainerFactory->newInstance();
149
        $child = $this->partBuilderFactory->newChildPartBuilder($headerContainer, $proxy);
150
        return $this->createPart($headerContainer, $child);
151
    }
152
}
153