Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit a005f92

Browse files
committed
Merge branch 'hotfix/7506'
Close zendframework/zendframework#7506
2 parents f97097e + 9c3698c commit a005f92

15 files changed

+402
-167
lines changed

src/Address.php

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
namespace Zend\Mail;
1111

12+
use Zend\Validator\EmailAddress as EmailAddressValidator;
13+
use Zend\Validator\Hostname;
14+
1215
class Address implements Address\AddressInterface
1316
{
1417
protected $email;
@@ -24,15 +27,33 @@ class Address implements Address\AddressInterface
2427
*/
2528
public function __construct($email, $name = null)
2629
{
27-
if (!is_string($email)) {
28-
throw new Exception\InvalidArgumentException('Email must be a string');
30+
$emailAddressValidator = new EmailAddressValidator(Hostname::ALLOW_LOCAL);
31+
if (! is_string($email) || empty($email)) {
32+
throw new Exception\InvalidArgumentException('Email must be a valid email address');
33+
}
34+
35+
if (preg_match("/[\r\n]/", $email)) {
36+
throw new Exception\InvalidArgumentException('CRLF injection detected');
37+
}
38+
39+
if (! $emailAddressValidator->isValid($email)) {
40+
$invalidMessages = $emailAddressValidator->getMessages();
41+
throw new Exception\InvalidArgumentException(array_shift($invalidMessages));
2942
}
30-
if (null !== $name && !is_string($name)) {
31-
throw new Exception\InvalidArgumentException('Name must be a string');
43+
44+
if (null !== $name) {
45+
if (! is_string($name)) {
46+
throw new Exception\InvalidArgumentException('Name must be a string');
47+
}
48+
49+
if (preg_match("/[\r\n]/", $name)) {
50+
throw new Exception\InvalidArgumentException('CRLF injection detected');
51+
}
52+
53+
$this->name = $name;
3254
}
3355

3456
$this->email = $email;
35-
$this->name = $name;
3657
}
3758

3859
/**
@@ -68,7 +89,6 @@ public function toString()
6889
return $string;
6990
}
7091

71-
$string = $name . ' ' . $string;
72-
return $string;
92+
return $name . ' ' . $string;
7393
}
7494
}

src/Header/ContentType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ public function getType()
124124
* @param string $name
125125
* @param string $value
126126
* @return ContentType
127-
* @throws InvalidArgumentException for parameter names that do not follow RFC 2822
128-
* @throws InvalidArgumentException for parameter values that do not follow RFC 2822
127+
* @throws Exception\InvalidArgumentException for parameter names that do not follow RFC 2822
128+
* @throws Exception\InvalidArgumentException for parameter values that do not follow RFC 2822
129129
*/
130130
public function addParameter($name, $value)
131131
{

src/Header/GenericHeader.php

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,16 @@ class GenericHeader implements HeaderInterface, UnstructuredInterface
2626
/**
2727
* Header encoding
2828
*
29-
* @var string
29+
* @var null|string
3030
*/
31-
protected $encoding = 'ASCII';
31+
protected $encoding;
3232

3333
public static function fromString($headerLine)
3434
{
3535
list($name, $value) = self::splitHeaderLine($headerLine);
36-
$decodedValue = HeaderWrap::mimeDecodeValue($value);
37-
$wasEncoded = ($decodedValue !== $value);
38-
$value = $decodedValue;
36+
$value = HeaderWrap::mimeDecodeValue($value);
3937
$header = new static($name, $value);
40-
if ($wasEncoded) {
41-
$header->setEncoding('UTF-8');
42-
}
38+
4339
return $header;
4440
}
4541

@@ -128,21 +124,17 @@ public function getFieldName()
128124
*/
129125
public function setFieldValue($fieldValue)
130126
{
131-
$fieldValue = (string) $fieldValue;
127+
$fieldValue = (string) $fieldValue;
132128

133-
// Raw values will be encoded when cast to string; as such we need to
134-
// mark them as quoted-printable to allow validation to work correctly.
135-
if (!HeaderWrap::canBeEncoded($fieldValue)) {
129+
if (! HeaderWrap::canBeEncoded($fieldValue)) {
136130
throw new Exception\InvalidArgumentException(
137131
'Header value must be composed of printable US-ASCII characters and valid folding sequences.'
138132
);
139133
}
140134

141-
if (!Mime::isPrintable($fieldValue)) {
142-
$this->setEncoding('UTF-8');
143-
}
144-
145135
$this->fieldValue = $fieldValue;
136+
$this->encoding = null;
137+
146138
return $this;
147139
}
148140

@@ -163,19 +155,20 @@ public function setEncoding($encoding)
163155

164156
public function getEncoding()
165157
{
158+
if (! $this->encoding) {
159+
$this->encoding = Mime::isPrintable($this->fieldValue) ? 'ASCII' : 'UTF-8';
160+
}
161+
166162
return $this->encoding;
167163
}
168164

169165
public function toString()
170166
{
171-
$name = $this->getFieldName();
167+
$name = $this->getFieldName();
172168
if (empty($name)) {
173-
throw new Exception\RuntimeException('Header name is not set, use setFieldName()');
169+
throw new Exception\RuntimeException('Header name is not set, use setFieldName()');
174170
}
175171
$value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
176-
if (empty($value)) {
177-
throw new Exception\RuntimeException('Header value is not set, use setFieldValue()');
178-
}
179172

180173
return $name . ': ' . $value;
181174
}

src/Header/GenericMultiHeader.php

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,17 @@ class GenericMultiHeader extends GenericHeader implements MultipleHeadersInterfa
1717
public static function fromString($headerLine)
1818
{
1919
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
20-
$decodedValue = HeaderWrap::mimeDecodeValue($fieldValue);
21-
$wasEncoded = ($decodedValue !== $fieldValue);
22-
$fieldValue = $decodedValue;
20+
$fieldValue = HeaderWrap::mimeDecodeValue($fieldValue);
2321

2422
if (strpos($fieldValue, ',')) {
2523
$headers = array();
26-
$encoding = ($wasEncoded) ? 'UTF-8' : 'ASCII';
2724
foreach (explode(',', $fieldValue) as $multiValue) {
28-
$header = new static($fieldName, $multiValue);
29-
$headers[] = $header->setEncoding($encoding);
25+
$headers[] = new static($fieldName, $multiValue);
3026
}
3127
return $headers;
32-
} else {
33-
$header = new static($fieldName, $fieldValue);
34-
if ($wasEncoded) {
35-
$header->setEncoding('UTF-8');
36-
}
37-
return $header;
3828
}
29+
30+
return new static($fieldName, $fieldValue);
3931
}
4032

4133
/**
@@ -47,16 +39,18 @@ public static function fromString($headerLine)
4739
*/
4840
public function toStringMultipleHeaders(array $headers)
4941
{
50-
$name = $this->getFieldName();
42+
$name = $this->getFieldName();
5143
$values = array($this->getFieldValue(HeaderInterface::FORMAT_ENCODED));
44+
5245
foreach ($headers as $header) {
53-
if (!$header instanceof static) {
46+
if (! $header instanceof static) {
5447
throw new Exception\InvalidArgumentException(
5548
'This method toStringMultipleHeaders was expecting an array of headers of the same type'
5649
);
5750
}
5851
$values[] = $header->getFieldValue(HeaderInterface::FORMAT_ENCODED);
5952
}
53+
6054
return $name . ': ' . implode(',', $values);
6155
}
6256
}

src/Header/Sender.php

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@
1010
namespace Zend\Mail\Header;
1111

1212
use Zend\Mail;
13+
use Zend\Mime\Mime;
1314

15+
/**
16+
* Sender header class methods.
17+
*
18+
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
19+
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
20+
*/
1421
class Sender implements HeaderInterface
1522
{
1623
/**
@@ -21,38 +28,35 @@ class Sender implements HeaderInterface
2128
/**
2229
* Header encoding
2330
*
24-
* @var string
31+
* @var null|string
2532
*/
26-
protected $encoding = 'ASCII';
33+
protected $encoding;
2734

2835
public static function fromString($headerLine)
2936
{
3037
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
31-
$decodedValue = HeaderWrap::mimeDecodeValue($value);
32-
$wasEncoded = ($decodedValue !== $value);
33-
$value = $decodedValue;
38+
$value = HeaderWrap::mimeDecodeValue($value);
3439

3540
// check to ensure proper header type for this factory
3641
if (strtolower($name) !== 'sender') {
3742
throw new Exception\InvalidArgumentException('Invalid header line for Sender string');
3843
}
3944

40-
$header = new static();
41-
if ($wasEncoded) {
42-
$header->setEncoding('UTF-8');
43-
}
45+
$header = new static();
46+
$senderName = '';
47+
$senderEmail = '';
4448

4549
// Check for address, and set if found
4650
if (preg_match('/^(?P<name>.*?)<(?P<email>[^>]+)>$/', $value, $matches)) {
47-
$name = $matches['name'];
48-
if (empty($name)) {
49-
$name = null;
50-
} else {
51-
$name = iconv_mime_decode($name, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
51+
$senderName = trim($matches['name']);
52+
if (empty($senderName)) {
53+
$senderName = null;
5254
}
53-
$header->setAddress($matches['email'], $name);
55+
$senderEmail = $matches['email'];
5456
}
5557

58+
$header->setAddress($senderEmail, $senderName);
59+
5660
return $header;
5761
}
5862

@@ -63,25 +67,23 @@ public function getFieldName()
6367

6468
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
6569
{
66-
if (!$this->address instanceof Mail\Address\AddressInterface) {
70+
if (! $this->address instanceof Mail\Address\AddressInterface) {
6771
return '';
6872
}
6973

7074
$email = sprintf('<%s>', $this->address->getEmail());
7175
$name = $this->address->getName();
7276

73-
HeaderValue::assertValid($email);
74-
HeaderValue::assertValid($name);
75-
7677
if (!empty($name)) {
77-
$encoding = $this->getEncoding();
78-
if ($format == HeaderInterface::FORMAT_ENCODED
79-
&& 'ASCII' !== $encoding
80-
) {
81-
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
78+
if ($format == HeaderInterface::FORMAT_ENCODED) {
79+
$encoding = $this->getEncoding();
80+
if ('ASCII' !== $encoding) {
81+
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
82+
}
8283
}
8384
$email = sprintf('%s %s', $name, $email);
8485
}
86+
8587
return $email;
8688
}
8789

@@ -93,6 +95,12 @@ public function setEncoding($encoding)
9395

9496
public function getEncoding()
9597
{
98+
if (! $this->encoding) {
99+
$this->encoding = Mime::isPrintable($this->getFieldValue(HeaderInterface::FORMAT_RAW))
100+
? 'ASCII'
101+
: 'UTF-8';
102+
}
103+
96104
return $this->encoding;
97105
}
98106

src/Header/Subject.php

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
namespace Zend\Mail\Header;
1111

12+
use Zend\Mime\Mime;
13+
14+
/**
15+
* Subject header class methods.
16+
*
17+
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
18+
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
19+
*/
1220
class Subject implements UnstructuredInterface
1321
{
1422
/**
@@ -19,26 +27,21 @@ class Subject implements UnstructuredInterface
1927
/**
2028
* Header encoding
2129
*
22-
* @var string
30+
* @var null|string
2331
*/
24-
protected $encoding = 'ASCII';
32+
protected $encoding;
2533

2634
public static function fromString($headerLine)
2735
{
2836
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
29-
$decodedValue = HeaderWrap::mimeDecodeValue($value);
30-
$wasEncoded = ($decodedValue !== $value);
31-
$value = $decodedValue;
37+
$value = HeaderWrap::mimeDecodeValue($value);
3238

3339
// check to ensure proper header type for this factory
3440
if (strtolower($name) !== 'subject') {
3541
throw new Exception\InvalidArgumentException('Invalid header line for Subject string');
3642
}
3743

3844
$header = new static();
39-
if ($wasEncoded) {
40-
$header->setEncoding('UTF-8');
41-
}
4245
$header->setSubject($value);
4346

4447
return $header;
@@ -66,16 +69,26 @@ public function setEncoding($encoding)
6669

6770
public function getEncoding()
6871
{
72+
if (! $this->encoding) {
73+
$this->encoding = Mime::isPrintable($this->subject) ? 'ASCII' : 'UTF-8';
74+
}
75+
6976
return $this->encoding;
7077
}
7178

7279
public function setSubject($subject)
7380
{
7481
$subject = (string) $subject;
75-
if (! HeaderValue::isValid($subject)) {
76-
throw new Exception\InvalidArgumentException('Invalid Subject value detected');
82+
83+
if (! HeaderWrap::canBeEncoded($subject)) {
84+
throw new Exception\InvalidArgumentException(
85+
'Subject value must be composed of printable US-ASCII or UTF-8 characters.'
86+
);
7787
}
78-
$this->subject = $subject;
88+
89+
$this->subject = $subject;
90+
$this->encoding = null;
91+
7992
return $this;
8093
}
8194

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy