Test Failed
Branch 1.0.0 (84f469)
by Zaahid
05:36
created

PartStreamFilterManager   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 0
dl 0
loc 140
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B attachTransferEncodingFilter() 0 17 5
A attachCharsetFilter() 0 18 4
A reset() 0 17 3
A attachContentStreamFilters() 0 9 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
namespace ZBateson\MailMimeParser\Message\Part;
8
9
/**
10
 * Manages attached stream filters for a MessagePart's content resource handle.
11
 * 
12
 * The attached stream filters are:
13
 *  o Content-Transfer-Encoding filter to manage decoding from a supported
14
 *    encoding: quoted-printable, base64 and x-uuencode.
15
 *  o Charset conversion filter to convert to UTF-8
16
 *
17
 * @author Zaahid Bateson
18
 */
19
class PartStreamFilterManager
20
{
21
    /**
22
     * @var resource compared against the passed $handle in
23
     *      attachContentStreamFilter to check that the attached filters are
24
     *      applied to the right handle (if it were to change.)
25
     */
26
    private $cachedHandle;
27
    
28
    /**
29
     * @var array map of the active encoding filter active on the current
30
     *      PartStreamFilterManager
31
     */
32
    private $encoding = [
33
        'type' => null,
34
        'filter' => null
35
    ];
36
    
37
    /**
38
     * @var array map of the active charset filter active on the current
39
     *      PartStreamFilterManager
40
     */
41
    private $charset = [
42
        'type' => null,
43
        'filter' => null
44
    ];
45
    
46
    /**
47
     * @var array mapping Content-Transfer-Encoding header values to available
48
     *      filters.
49
     */
50
    private $encodingEncoderMap = [
51
        'quoted-printable' => 'mmp-convert.quoted-printable-decode',
52
        'base64' => 'mmp-convert.base64-decode',
53
        'x-uuencode' => 'mailmimeparser-uudecode'
54
    ];
55
    
56
    /**
57
     * Attaches a decoding filter to the given handle, for the passed
58
     * $transferEncoding if not already attached to the handle.
59
     * 
60
     * Checks the value of $this->encoding['type'] against the passed
61
     * $transferEncoding, and, if identical, does nothing.  Otherwise detaches
62
     * any attached transfer encoding decoder filters before attaching a
63
     * relevant one and updating $this->encoding['type'].
64
     * 
65
     * @param resource $handle
66
     * @param string $transferEncoding
67
     */
68
    protected function attachTransferEncodingFilter($handle, $transferEncoding)
69
    {
70
        if ($transferEncoding !== $this->encoding['type']) {
71
            if (is_resource($this->encoding['filter'])) {
72
                stream_filter_remove($this->encoding['filter']);
73
                $this->encoding['filter'] = null;
74
            }
75
            if (!empty($transferEncoding) && isset($this->encodingEncoderMap[$transferEncoding])) {
76
                $this->encoding['filter'] = stream_filter_append(
77
                    $handle,
78
                    $this->encodingEncoderMap[$transferEncoding],
79
                    STREAM_FILTER_READ
80
                );
81
            }
82
            $this->encoding['type'] = $transferEncoding;
83
        }
84
    }
85
    
86
    /**
87
     * Attaches a charset conversion filter to the given handle, for the passed
88
     * $charset if not already attached to the handle.
89
     * 
90
     * Checks the value of $this->charset['type'] against the passed $charset,
91
     * and, if identical, does nothing.  Otherwise detaches any attached charset
92
     * conversion filters before attaching a relevant one and updating
93
     * $this->charset['type'].
94
     * 
95
     * @param resource $handle
96
     * @param string $charset
97
     */
98
    protected function attachCharsetFilter($handle, $charset)
99
    {
100
        if ($charset !== $this->charset['type']) {
101
            if (is_resource($this->charset['filter'])) {
102
                stream_filter_remove($this->charset['filter']);
103
                $this->charset['filter'] = null;
104
            }
105
            if (!empty($charset)) {
106
                $this->charset['filter'] = stream_filter_append(
107
                    $handle,
108
                    'mailmimeparser-encode',
109
                    STREAM_FILTER_READ,
110
                    [ 'charset' => $charset ]
111
                );
112
            }
113
            $this->charset['type'] = $charset;
114
        }
115
    }
116
    
117
    /**
118
     * Resets attached transfer-encoding decoder and charset conversion filters
119
     * set for the current manager.
120
     */
121
    public function reset()
122
    {
123
        if (is_resource($this->encoding['filter'])) {
124
            @stream_filter_remove($this->encoding['filter']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
125
        }
126
        if (is_resource($this->charset['filter'])) {
127
            @stream_filter_remove($this->charset['filter']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
128
        }
129
        $this->encoding = [
130
            'type' => null,
131
            'filter' => null
132
        ];
133
        $this->charset = [
134
            'type' => null,
135
            'filter' => null
136
        ];
137
    }
138
    
139
    /**
140
     * Checks what transfer-encoding decoder filters and charset conversion
141
     * filters are attached on the handle, detaching them if necessary, before
142
     * attaching relevant filters for the passed $transferEncoding and
143
     * $charset.
144
     * 
145
     * @param resource $handle
146
     * @param string $transferEncoding
147
     * @param string $charset
148
     */
149
    public function attachContentStreamFilters($handle, $transferEncoding, $charset)
150
    {
151
        if ($this->cachedHandle !== $handle) {
152
            $this->reset();
153
            $this->cachedHandle = $handle;
154
        }
155
        $this->attachTransferEncodingFilter($handle, $transferEncoding);
156
        $this->attachCharsetFilter($handle, $charset);
157
    }
158
}
159