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\Header\Part; |
9
|
|
|
|
10
|
|
|
use Psr\Log\LoggerInterface; |
11
|
|
|
use ZBateson\MbWrapper\MbWrapper; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Holds a running value for an RFC-2231 split header parameter. |
15
|
|
|
* |
16
|
|
|
* ParameterConsumer creates SplitParameterTokens when a split header parameter |
17
|
|
|
* is first found, and adds subsequent split parts to an already created one if |
18
|
|
|
* the parameter name matches. |
19
|
|
|
* |
20
|
|
|
* @author Zaahid Bateson |
21
|
|
|
*/ |
22
|
|
|
class SplitParameterPart extends ParameterPart |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @var HeaderPartFactory used to create combined MimeToken parts. |
26
|
|
|
*/ |
27
|
|
|
protected HeaderPartFactory $partFactory; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Initializes a SplitParameterToken. |
31
|
|
|
* |
32
|
|
|
* @param ParameterPart[] $children |
33
|
|
|
*/ |
34
|
|
|
public function __construct( |
35
|
|
|
LoggerInterface $logger, |
36
|
|
|
MbWrapper $charsetConverter, |
37
|
|
|
HeaderPartFactory $headerPartFactory, |
38
|
|
|
array $children |
39
|
|
|
) { |
40
|
|
|
$this->partFactory = $headerPartFactory; |
41
|
|
|
NameValuePart::__construct($logger, $charsetConverter, [$children[0]], $children); |
42
|
|
|
$this->children = $children; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
protected function getNameFromParts(array $parts) : string |
46
|
|
|
{ |
47
|
|
|
return $parts[0]->getName(); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
private function getMimeTokens(string $value) : array |
51
|
|
|
{ |
52
|
|
|
$pattern = MimeToken::MIME_PART_PATTERN; |
53
|
|
|
// remove whitespace between two adjacent mime encoded parts |
54
|
|
|
$normed = \preg_replace("/($pattern)\\s+(?=$pattern)/", '$1', $value); |
55
|
|
|
// with PREG_SPLIT_DELIM_CAPTURE, matched and unmatched parts are returned |
56
|
|
|
$aMimeParts = \preg_split("/($pattern)/", $normed, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); |
57
|
|
|
return \array_map( |
58
|
|
|
fn ($p) => (\preg_match("/$pattern/", $p)) ? $this->partFactory->newMimeToken($p) : $this->partFactory->newToken($p, true, true), |
59
|
|
|
$aMimeParts |
60
|
|
|
); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
private function combineAdjacentUnencodedParts(array $parts) : array |
64
|
|
|
{ |
65
|
|
|
$runningValue = ''; |
66
|
|
|
$returnedParts = []; |
67
|
|
|
foreach ($parts as $part) { |
68
|
|
|
if (!$part->encoded) { |
69
|
|
|
$runningValue .= $part->value; |
70
|
|
|
continue; |
71
|
|
|
} |
72
|
|
|
if (!empty($runningValue)) { |
73
|
|
|
$returnedParts = \array_merge($returnedParts, $this->getMimeTokens($runningValue)); |
74
|
|
|
$runningValue = ''; |
75
|
|
|
} |
76
|
|
|
$returnedParts[] = $part; |
77
|
|
|
} |
78
|
|
|
if (!empty($runningValue)) { |
79
|
|
|
$returnedParts = \array_merge($returnedParts, $this->getMimeTokens($runningValue)); |
80
|
|
|
} |
81
|
|
|
return $returnedParts; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
protected function getValueFromParts(array $parts) : string |
85
|
|
|
{ |
86
|
|
|
$sorted = $parts; |
87
|
|
|
\usort($sorted, fn ($a, $b) => $a->index <=> $b->index); |
88
|
|
|
|
89
|
|
|
$first = $sorted[0]; |
90
|
|
|
$this->language = $first->language; |
91
|
|
|
$charset = $this->charset = $first->charset; |
92
|
|
|
|
93
|
|
|
$combined = $this->combineAdjacentUnencodedParts($sorted); |
94
|
|
|
|
95
|
|
|
return \implode(\array_map( |
96
|
|
|
fn ($p) => ($p instanceof ParameterPart && $p->encoded) |
97
|
|
|
? $this->decodePartValue($p->getValue(), ($p->charset === null) ? $charset : $p->charset) |
98
|
|
|
: $p->getValue(), |
99
|
|
|
$combined |
100
|
|
|
)); |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
|