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\Header\Part; |
8
|
|
|
|
9
|
|
|
use ZBateson\MailMimeParser\Util\CharsetConverter; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Holds a running value for an RFC-2231 split header parameter. |
13
|
|
|
* |
14
|
|
|
* ParameterConsumer creates SplitParameterTokens when a split header parameter |
15
|
|
|
* is first found, and adds subsequent split parts to an already created one if |
16
|
|
|
* the parameter name matches. |
17
|
|
|
* |
18
|
|
|
* @author Zaahid Bateson |
19
|
|
|
*/ |
20
|
|
|
class SplitParameterToken extends HeaderPart |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* @var string name of the parameter. |
24
|
|
|
*/ |
25
|
|
|
protected $name; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var string[] keeps encoded parts values that need to be decoded. Keys |
29
|
|
|
* are set to the index part of the split parameter and used for |
30
|
|
|
* sorting before decoding/concatenating. |
31
|
|
|
*/ |
32
|
|
|
protected $encodedParts = []; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var string contains literal parts that don't require any decoding (and |
36
|
|
|
* are therefore ISO-8859-1 (technically should be 7bit US-ASCII but |
37
|
|
|
* allowing 8bit shouldn't be an issue as elsewhere in MMP). |
38
|
|
|
*/ |
39
|
|
|
protected $literalParts = []; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var string RFC-1766 (or subset) language code with optional subtags, |
43
|
|
|
* regions, etc... |
44
|
|
|
*/ |
45
|
|
|
protected $language; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var string charset of content in $encodedParts. |
49
|
|
|
*/ |
50
|
|
|
protected $charset = 'ISO-8859-1'; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Initializes a SplitParameterToken. |
54
|
|
|
* |
55
|
|
|
* @param CharsetConverter $charsetConverter |
56
|
|
|
* @param string $name the parameter's name |
57
|
|
|
*/ |
58
|
|
|
public function __construct(CharsetConverter $charsetConverter, $name) |
59
|
|
|
{ |
60
|
|
|
parent::__construct($charsetConverter, ''); |
|
|
|
|
61
|
|
|
$this->name = trim($name); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Extracts charset and language from an encoded value, setting them on the |
66
|
|
|
* current object if $index is 0 and adds the value part to the encodedParts |
67
|
|
|
* array. |
68
|
|
|
* |
69
|
|
|
* @param string $value |
70
|
|
|
* @param int $index |
71
|
|
|
*/ |
72
|
|
|
protected function extractMetaInformationAndValue($value, $index) |
73
|
|
|
{ |
74
|
|
|
if (preg_match('~^([^\']*)\'([^\']*)\'(.*)$~', $value, $matches)) { |
75
|
|
|
if ($index === 0) { |
76
|
|
|
$this->charset = (!empty($matches[1])) ? $matches[1] : $this->charset; |
77
|
|
|
$this->language = (!empty($matches[2])) ? $matches[2] : $this->language; |
78
|
|
|
} |
79
|
|
|
$value = $matches[3]; |
80
|
|
|
} |
81
|
|
|
$this->encodedParts[$index] = $value; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Adds the passed part to the running array of values. |
86
|
|
|
* |
87
|
|
|
* If $isEncoded is true, language and charset info is extracted from the |
88
|
|
|
* value, and the value is decoded before returning in getValue. |
89
|
|
|
* |
90
|
|
|
* The value of the parameter is sorted based on the passed $index |
91
|
|
|
* arguments when adding before concatenating when re-constructing the |
92
|
|
|
* value. |
93
|
|
|
* |
94
|
|
|
* @param string $value |
95
|
|
|
* @param boolean $isEncoded |
96
|
|
|
* @param int $index |
97
|
|
|
*/ |
98
|
|
|
public function addPart($value, $isEncoded, $index) |
99
|
|
|
{ |
100
|
|
|
if (empty($index)) { |
101
|
|
|
$index = 0; |
102
|
|
|
} |
103
|
|
|
if ($isEncoded) { |
104
|
|
|
$this->extractMetaInformationAndValue($value, $index); |
105
|
|
|
} else { |
106
|
|
|
$this->literalParts[$index] = $this->convertEncoding($value); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Traverses $this->encodedParts until a non-sequential key is found, or the |
112
|
|
|
* end of the array is found. |
113
|
|
|
* |
114
|
|
|
* This allows encoded parts of a split parameter to be split anywhere and |
115
|
|
|
* reconstructed. |
116
|
|
|
* |
117
|
|
|
* The returned string is converted to UTF-8 before being returned. |
118
|
|
|
* |
119
|
|
|
* @return string |
120
|
|
|
*/ |
121
|
|
|
private function getNextEncodedValue() |
122
|
|
|
{ |
123
|
|
|
$cur = current($this->encodedParts); |
124
|
|
|
$key = key($this->encodedParts); |
125
|
|
|
$running = ''; |
126
|
|
|
while ($cur !== false) { |
127
|
|
|
$running .= $cur; |
128
|
|
|
$cur = next($this->encodedParts); |
129
|
|
|
$nKey = key($this->encodedParts); |
130
|
|
|
if ($nKey !== $key + 1) { |
131
|
|
|
break; |
132
|
|
|
} |
133
|
|
|
$key = $nKey; |
134
|
|
|
} |
135
|
|
|
return $this->convertEncoding( |
136
|
|
|
rawurldecode($running), |
137
|
|
|
$this->charset, |
138
|
|
|
true |
139
|
|
|
); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Reconstructs the value of the split parameter into a single UTF-8 string |
144
|
|
|
* and returns it. |
145
|
|
|
* |
146
|
|
|
* @return string |
147
|
|
|
*/ |
148
|
|
|
public function getValue() |
149
|
|
|
{ |
150
|
|
|
$parts = $this->literalParts; |
151
|
|
|
|
152
|
|
|
reset($this->encodedParts); |
153
|
|
|
ksort($this->encodedParts); |
154
|
|
|
while (current($this->encodedParts) !== false) { |
155
|
|
|
$parts[key($this->encodedParts)] = $this->getNextEncodedValue(); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
ksort($parts); |
159
|
|
|
return array_reduce( |
160
|
|
|
$parts, |
161
|
|
|
function ($carry, $item) { |
162
|
|
|
return $carry . $item; |
163
|
|
|
}, |
164
|
|
|
'' |
165
|
|
|
); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Returns the name of the parameter. |
170
|
|
|
* |
171
|
|
|
* @return string |
172
|
|
|
*/ |
173
|
|
|
public function getName() |
174
|
|
|
{ |
175
|
|
|
return $this->name; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Returns the language of the parameter if set, or null if not. |
180
|
|
|
* |
181
|
|
|
* @return string |
182
|
|
|
*/ |
183
|
|
|
public function getLanguage() |
184
|
|
|
{ |
185
|
|
|
return $this->language; |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.