composer package updates
[openemr.git] / vendor / zendframework / zend-mail / src / Header / AbstractAddressList.php
blobab48f67187284551ba332adfe0fca95d69fb25f9
1 <?php
2 /**
3 * @see https://github.com/zendframework/zend-mail for the canonical source repository
4 * @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
5 * @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
6 */
8 namespace Zend\Mail\Header;
10 use TrueBV\Exception\OutOfBoundsException;
11 use TrueBV\Punycode;
12 use Zend\Mail\Address;
13 use Zend\Mail\AddressList;
14 use Zend\Mail\Headers;
16 /**
17 * Base class for headers composing address lists (to, from, cc, bcc, reply-to)
19 abstract class AbstractAddressList implements HeaderInterface
21 /**
22 * @var AddressList
24 protected $addressList;
26 /**
27 * @var string Normalized field name
29 protected $fieldName;
31 /**
32 * Header encoding
34 * @var string
36 protected $encoding = 'ASCII';
38 /**
39 * @var string lower case field name
41 protected static $type;
43 /**
44 * @var Punycode|null
46 private static $punycode;
48 public static function fromString($headerLine)
50 list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
51 if (strtolower($fieldName) !== static::$type) {
52 throw new Exception\InvalidArgumentException(sprintf(
53 'Invalid header line for "%s" string',
54 __CLASS__
55 ));
58 // split value on ","
59 $fieldValue = str_replace(Headers::FOLDING, ' ', $fieldValue);
60 $fieldValue = preg_replace('/[^:]+:([^;]*);/', '$1,', $fieldValue);
61 $values = ListParser::parse($fieldValue);
63 $wasEncoded = false;
64 $addresses = array_map(
65 function ($value) use (&$wasEncoded) {
66 $decodedValue = HeaderWrap::mimeDecodeValue($value);
67 $wasEncoded = $wasEncoded || ($decodedValue !== $value);
69 $value = trim($decodedValue);
71 $comments = self::getComments($value);
72 $value = self::stripComments($value);
74 $value = preg_replace(
76 '#(?<!\\\)"(.*)(?<!\\\)"#', // quoted-text
77 '#\\\([\x01-\x09\x0b\x0c\x0e-\x7f])#', // quoted-pair
80 '\\1',
81 '\\1',
83 $value
86 return empty($value) ? null : Address::fromString($value, $comments);
88 $values
90 $addresses = array_filter($addresses);
92 $header = new static();
93 if ($wasEncoded) {
94 $header->setEncoding('UTF-8');
97 /** @var AddressList $addressList */
98 $addressList = $header->getAddressList();
99 foreach ($addresses as $address) {
100 $addressList->add($address);
103 return $header;
106 public function getFieldName()
108 return $this->fieldName;
112 * Safely convert UTF-8 encoded domain name to ASCII
113 * @param string $domainName the UTF-8 encoded email
114 * @return string
116 protected function idnToAscii($domainName)
118 if (null === self::$punycode) {
119 self::$punycode = new Punycode();
121 try {
122 return self::$punycode->encode($domainName);
123 } catch (OutOfBoundsException $e) {
124 return $domainName;
128 public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
130 $emails = [];
131 $encoding = $this->getEncoding();
133 foreach ($this->getAddressList() as $address) {
134 $email = $address->getEmail();
135 $name = $address->getName();
137 if (! empty($name) && false !== strstr($name, ',')) {
138 $name = sprintf('"%s"', $name);
141 if ($format === HeaderInterface::FORMAT_ENCODED
142 && 'ASCII' !== $encoding
144 if (! empty($name)) {
145 $name = HeaderWrap::mimeEncodeValue($name, $encoding);
148 if (preg_match('/^(.+)@([^@]+)$/', $email, $matches)) {
149 $localPart = $matches[1];
150 $hostname = $this->idnToAscii($matches[2]);
151 $email = sprintf('%s@%s', $localPart, $hostname);
155 if (empty($name)) {
156 $emails[] = $email;
157 } else {
158 $emails[] = sprintf('%s <%s>', $name, $email);
162 // Ensure the values are valid before sending them.
163 if ($format !== HeaderInterface::FORMAT_RAW) {
164 foreach ($emails as $email) {
165 HeaderValue::assertValid($email);
169 return implode(',' . Headers::FOLDING, $emails);
172 public function setEncoding($encoding)
174 $this->encoding = $encoding;
175 return $this;
178 public function getEncoding()
180 return $this->encoding;
184 * Set address list for this header
186 * @param AddressList $addressList
188 public function setAddressList(AddressList $addressList)
190 $this->addressList = $addressList;
194 * Get address list managed by this header
196 * @return AddressList
198 public function getAddressList()
200 if (null === $this->addressList) {
201 $this->setAddressList(new AddressList());
203 return $this->addressList;
206 public function toString()
208 $name = $this->getFieldName();
209 $value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
210 return (empty($value)) ? '' : sprintf('%s: %s', $name, $value);
214 * Retrieve comments from value, if any.
216 * Supposed to be private, protected as a workaround for PHP bug 68194
218 * @param string $value
219 * @return string
221 protected static function getComments($value)
223 $matches = [];
224 preg_match_all(
225 '/\\(
226 (?P<comment>(
227 \\\\.|
228 [^\\\\)]
230 \\)/x',
231 $value,
232 $matches
234 return isset($matches['comment']) ? implode(', ', $matches['comment']) : '';
238 * Strip all comments from value, if any.
240 * Supposed to be private, protected as a workaround for PHP bug 68194
242 * @param string $value
243 * @return void
245 protected static function stripComments($value)
247 return preg_replace(
248 '/\\(
250 \\\\.|
251 [^\\\\)]
253 \\)/x',
255 $value