PageRenderTime 29ms CodeModel.GetById 1ms app.highlight 19ms RepoModel.GetById 2ms app.codeStats 0ms

/framework/vendor/swift/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php

http://zoop.googlecode.com/
PHP | 274 lines | 144 code | 27 blank | 103 comment | 15 complexity | 546829916217f50d005696795ccb9431 MD5 | raw file
  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 */
 22class 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}