TYPO3 API  SVNRelease
ParameterizedHeader.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*
00004  * This file is part of SwiftMailer.
00005  * (c) 2004-2009 Chris Corbyn
00006  *
00007  * For the full copyright and license information, please view the LICENSE
00008  * file that was distributed with this source code.
00009  */
00010 
00011 //@require 'Swift/Mime/Headers/UnstructuredHeader.php';
00012 //@require 'Swift/Mime/HeaderEncoder.php';
00013 //@require 'Swift/Mime/ParameterizedHeader.php';
00014 //@require 'Swift/Encoder.php';
00015 
00016 /**
00017  * An abstract base MIME Header.
00018  * @package Swift
00019  * @subpackage Mime
00020  * @author Chris Corbyn
00021  */
00022 class Swift_Mime_Headers_ParameterizedHeader
00023   extends Swift_Mime_Headers_UnstructuredHeader
00024   implements Swift_Mime_ParameterizedHeader
00025 {
00026 
00027   /**
00028    * The Encoder used to encode the parameters.
00029    * @var Swift_Encoder
00030    * @access private
00031    */
00032   private $_paramEncoder;
00033 
00034   /**
00035    * The parameters as an associative array.
00036    * @var string[]
00037    * @access private
00038    */
00039   private $_params = array();
00040 
00041   /**
00042    * RFC 2231's definition of a token.
00043    * @var string
00044    * @access private
00045    */
00046   private $_tokenRe;
00047 
00048   /**
00049    * Creates a new ParameterizedHeader with $name.
00050    * @param string $name
00051    * @param Swift_Mime_HeaderEncoder $encoder
00052    * @param Swift_Encoder $paramEncoder, optional
00053    */
00054   public function __construct($name, Swift_Mime_HeaderEncoder $encoder,
00055     Swift_Encoder $paramEncoder = null)
00056   {
00057     $this->setFieldName($name);
00058     $this->setEncoder($encoder);
00059     $this->_paramEncoder = $paramEncoder;
00060     $this->initializeGrammar();
00061     $this->_tokenRe = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
00062   }
00063 
00064   /**
00065    * Get the type of Header that this instance represents.
00066    * @return int
00067    * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
00068    * @see TYPE_DATE, TYPE_ID, TYPE_PATH
00069    */
00070   public function getFieldType()
00071   {
00072     return self::TYPE_PARAMETERIZED;
00073   }
00074 
00075   /**
00076    * Set the character set used in this Header.
00077    * @param string $charset
00078    */
00079   public function setCharset($charset)
00080   {
00081     parent::setCharset($charset);
00082     if (isset($this->_paramEncoder))
00083     {
00084       $this->_paramEncoder->charsetChanged($charset);
00085     }
00086   }
00087 
00088   /**
00089    * Set the value of $parameter.
00090    * @param string $parameter
00091    * @param string $value
00092    */
00093   public function setParameter($parameter, $value)
00094   {
00095     $this->setParameters(array_merge($this->getParameters(), array($parameter => $value)));
00096   }
00097 
00098   /**
00099    * Get the value of $parameter.
00100    * @return string
00101    */
00102   public function getParameter($parameter)
00103   {
00104     $params = $this->getParameters();
00105     return array_key_exists($parameter, $params)
00106       ? $params[$parameter]
00107       : null;
00108   }
00109 
00110   /**
00111    * Set an associative array of parameter names mapped to values.
00112    * @param string[]
00113    */
00114   public function setParameters(array $parameters)
00115   {
00116     $this->clearCachedValueIf($this->_params != $parameters);
00117     $this->_params = $parameters;
00118   }
00119 
00120   /**
00121    * Returns an associative array of parameter names mapped to values.
00122    * @return string[]
00123    */
00124   public function getParameters()
00125   {
00126     return $this->_params;
00127   }
00128 
00129   /**
00130    * Get the value of this header prepared for rendering.
00131    * @return string
00132    */
00133   public function getFieldBody() //TODO: Check caching here
00134   {
00135     $body = parent::getFieldBody();
00136     foreach ($this->_params as $name => $value)
00137     {
00138       if (!is_null($value))
00139       {
00140         //Add the parameter
00141         $body .= '; ' . $this->_createParameter($name, $value);
00142       }
00143     }
00144     return $body;
00145   }
00146 
00147   // -- Protected methods
00148 
00149   /**
00150    * Generate a list of all tokens in the final header.
00151    * This doesn't need to be overridden in theory, but it is for implementation
00152    * reasons to prevent potential breakage of attributes.
00153    * @return string[]
00154    * @access protected
00155    */
00156   protected function toTokens($string = null)
00157   {
00158     $tokens = parent::toTokens(parent::getFieldBody());
00159 
00160     //Try creating any parameters
00161     foreach ($this->_params as $name => $value)
00162     {
00163       if (!is_null($value))
00164       {
00165         //Add the semi-colon separator
00166         $tokens[count($tokens)-1] .= ';';
00167         $tokens = array_merge($tokens, $this->generateTokenLines(
00168           ' ' . $this->_createParameter($name, $value)
00169           ));
00170       }
00171     }
00172 
00173     return $tokens;
00174   }
00175 
00176   // -- Private methods
00177 
00178   /**
00179    * Render a RFC 2047 compliant header parameter from the $name and $value.
00180    * @param string $name
00181    * @param string $value
00182    * @return string
00183    * @access private
00184    */
00185   private function _createParameter($name, $value)
00186   {
00187     $origValue = $value;
00188 
00189     $encoded = false;
00190     //Allow room for parameter name, indices, "=" and DQUOTEs
00191     $maxValueLength = $this->getMaxLineLength() - strlen($name . '=*N"";') - 1;
00192     $firstLineOffset = 0;
00193 
00194     //If it's not already a valid parameter value...
00195     if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
00196     {
00197       //TODO: text, or something else??
00198       //... and it's not ascii
00199       if (!preg_match('/^' . $this->getGrammar('text') . '*$/D', $value))
00200       {
00201         $encoded = true;
00202         //Allow space for the indices, charset and language
00203         $maxValueLength = $this->getMaxLineLength() - strlen($name . '*N*="";') - 1;
00204         $firstLineOffset = strlen(
00205           $this->getCharset() . "'" . $this->getLanguage() . "'"
00206           );
00207       }
00208     }
00209 
00210     //Encode if we need to
00211     if ($encoded || strlen($value) > $maxValueLength)
00212     {
00213       if (isset($this->_paramEncoder))
00214       {
00215         $value = $this->_paramEncoder->encodeString(
00216           $origValue, $firstLineOffset, $maxValueLength
00217           );
00218       }
00219       else //We have to go against RFC 2183/2231 in some areas for interoperability
00220       {
00221         $value = $this->getTokenAsEncodedWord($origValue);
00222         $encoded = false;
00223       }
00224     }
00225 
00226     $valueLines = isset($this->_paramEncoder) ? explode("\r\n", $value) : array($value);
00227 
00228     //Need to add indices
00229     if (count($valueLines) > 1)
00230     {
00231       $paramLines = array();
00232       foreach ($valueLines as $i => $line)
00233       {
00234         $paramLines[] = $name . '*' . $i .
00235           $this->_getEndOfParameterValue($line, $encoded, $i == 0);
00236       }
00237       return implode(";\r\n ", $paramLines);
00238     }
00239     else
00240     {
00241       return $name . $this->_getEndOfParameterValue(
00242         $valueLines[0], $encoded, true
00243         );
00244     }
00245   }
00246 
00247   /**
00248    * Returns the parameter value from the "=" and beyond.
00249    * @param string $value to append
00250    * @param boolean $encoded
00251    * @param boolean $firstLine
00252    * @return string
00253    * @access private
00254    */
00255   private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
00256   {
00257     if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
00258     {
00259       $value = '"' . $value . '"';
00260     }
00261     $prepend = '=';
00262     if ($encoded)
00263     {
00264       $prepend = '*=';
00265       if ($firstLine)
00266       {
00267         $prepend = '*=' . $this->getCharset() . "'" . $this->getLanguage() .
00268           "'";
00269       }
00270     }
00271     return $prepend . $value;
00272   }
00273 
00274 }