Added feature #15998: Create a new API to send mails based on SwiftMailer to replace...
[Packages/TYPO3.CMS.git] / typo3 / contrib / swiftmailer / classes / Swift / Mime / Headers / ParameterizedHeader.php
1 <?php
2
3 /*
4 * This file is part of SwiftMailer.
5 * (c) 2004-2009 Chris Corbyn
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 //@require 'Swift/Mime/Headers/UnstructuredHeader.php';
12 //@require 'Swift/Mime/HeaderEncoder.php';
13 //@require 'Swift/Mime/ParameterizedHeader.php';
14 //@require 'Swift/Encoder.php';
15
16 /**
17 * An abstract base MIME Header.
18 * @package Swift
19 * @subpackage Mime
20 * @author Chris Corbyn
21 */
22 class Swift_Mime_Headers_ParameterizedHeader
23 extends Swift_Mime_Headers_UnstructuredHeader
24 implements Swift_Mime_ParameterizedHeader
25 {
26
27 /**
28 * The Encoder used to encode the parameters.
29 * @var Swift_Encoder
30 * @access private
31 */
32 private $_paramEncoder;
33
34 /**
35 * The parameters as an associative array.
36 * @var string[]
37 * @access private
38 */
39 private $_params = array();
40
41 /**
42 * RFC 2231's definition of a token.
43 * @var string
44 * @access private
45 */
46 private $_tokenRe;
47
48 /**
49 * Creates a new ParameterizedHeader with $name.
50 * @param string $name
51 * @param Swift_Mime_HeaderEncoder $encoder
52 * @param Swift_Encoder $paramEncoder, optional
53 */
54 public function __construct($name, Swift_Mime_HeaderEncoder $encoder,
55 Swift_Encoder $paramEncoder = null)
56 {
57 $this->setFieldName($name);
58 $this->setEncoder($encoder);
59 $this->_paramEncoder = $paramEncoder;
60 $this->initializeGrammar();
61 $this->_tokenRe = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
62 }
63
64 /**
65 * Get the type of Header that this instance represents.
66 * @return int
67 * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
68 * @see TYPE_DATE, TYPE_ID, TYPE_PATH
69 */
70 public function getFieldType()
71 {
72 return self::TYPE_PARAMETERIZED;
73 }
74
75 /**
76 * Set the character set used in this Header.
77 * @param string $charset
78 */
79 public function setCharset($charset)
80 {
81 parent::setCharset($charset);
82 if (isset($this->_paramEncoder))
83 {
84 $this->_paramEncoder->charsetChanged($charset);
85 }
86 }
87
88 /**
89 * Set the value of $parameter.
90 * @param string $parameter
91 * @param string $value
92 */
93 public function setParameter($parameter, $value)
94 {
95 $this->setParameters(array_merge($this->getParameters(), array($parameter => $value)));
96 }
97
98 /**
99 * Get the value of $parameter.
100 * @return string
101 */
102 public function getParameter($parameter)
103 {
104 $params = $this->getParameters();
105 return array_key_exists($parameter, $params)
106 ? $params[$parameter]
107 : null;
108 }
109
110 /**
111 * Set an associative array of parameter names mapped to values.
112 * @param string[]
113 */
114 public function setParameters(array $parameters)
115 {
116 $this->clearCachedValueIf($this->_params != $parameters);
117 $this->_params = $parameters;
118 }
119
120 /**
121 * Returns an associative array of parameter names mapped to values.
122 * @return string[]
123 */
124 public function getParameters()
125 {
126 return $this->_params;
127 }
128
129 /**
130 * Get the value of this header prepared for rendering.
131 * @return string
132 */
133 public function getFieldBody() //TODO: Check caching here
134 {
135 $body = parent::getFieldBody();
136 foreach ($this->_params as $name => $value)
137 {
138 if (!is_null($value))
139 {
140 //Add the parameter
141 $body .= '; ' . $this->_createParameter($name, $value);
142 }
143 }
144 return $body;
145 }
146
147 // -- Protected methods
148
149 /**
150 * Generate a list of all tokens in the final header.
151 * This doesn't need to be overridden in theory, but it is for implementation
152 * reasons to prevent potential breakage of attributes.
153 * @return string[]
154 * @access protected
155 */
156 protected function toTokens($string = null)
157 {
158 $tokens = parent::toTokens(parent::getFieldBody());
159
160 //Try creating any parameters
161 foreach ($this->_params as $name => $value)
162 {
163 if (!is_null($value))
164 {
165 //Add the semi-colon separator
166 $tokens[count($tokens)-1] .= ';';
167 $tokens = array_merge($tokens, $this->generateTokenLines(
168 ' ' . $this->_createParameter($name, $value)
169 ));
170 }
171 }
172
173 return $tokens;
174 }
175
176 // -- Private methods
177
178 /**
179 * Render a RFC 2047 compliant header parameter from the $name and $value.
180 * @param string $name
181 * @param string $value
182 * @return string
183 * @access private
184 */
185 private function _createParameter($name, $value)
186 {
187 $origValue = $value;
188
189 $encoded = false;
190 //Allow room for parameter name, indices, "=" and DQUOTEs
191 $maxValueLength = $this->getMaxLineLength() - strlen($name . '=*N"";') - 1;
192 $firstLineOffset = 0;
193
194 //If it's not already a valid parameter value...
195 if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
196 {
197 //TODO: text, or something else??
198 //... and it's not ascii
199 if (!preg_match('/^' . $this->getGrammar('text') . '*$/D', $value))
200 {
201 $encoded = true;
202 //Allow space for the indices, charset and language
203 $maxValueLength = $this->getMaxLineLength() - strlen($name . '*N*="";') - 1;
204 $firstLineOffset = strlen(
205 $this->getCharset() . "'" . $this->getLanguage() . "'"
206 );
207 }
208 }
209
210 //Encode if we need to
211 if ($encoded || strlen($value) > $maxValueLength)
212 {
213 if (isset($this->_paramEncoder))
214 {
215 $value = $this->_paramEncoder->encodeString(
216 $origValue, $firstLineOffset, $maxValueLength
217 );
218 }
219 else //We have to go against RFC 2183/2231 in some areas for interoperability
220 {
221 $value = $this->getTokenAsEncodedWord($origValue);
222 $encoded = false;
223 }
224 }
225
226 $valueLines = isset($this->_paramEncoder) ? explode("\r\n", $value) : array($value);
227
228 //Need to add indices
229 if (count($valueLines) > 1)
230 {
231 $paramLines = array();
232 foreach ($valueLines as $i => $line)
233 {
234 $paramLines[] = $name . '*' . $i .
235 $this->_getEndOfParameterValue($line, $encoded, $i == 0);
236 }
237 return implode(";\r\n ", $paramLines);
238 }
239 else
240 {
241 return $name . $this->_getEndOfParameterValue(
242 $valueLines[0], $encoded, true
243 );
244 }
245 }
246
247 /**
248 * Returns the parameter value from the "=" and beyond.
249 * @param string $value to append
250 * @param boolean $encoded
251 * @param boolean $firstLine
252 * @return string
253 * @access private
254 */
255 private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
256 {
257 if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
258 {
259 $value = '"' . $value . '"';
260 }
261 $prepend = '=';
262 if ($encoded)
263 {
264 $prepend = '*=';
265 if ($firstLine)
266 {
267 $prepend = '*=' . $this->getCharset() . "'" . $this->getLanguage() .
268 "'";
269 }
270 }
271 return $prepend . $value;
272 }
273
274 }