[ Index ]

MailPress 544

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]    

title

Body

[close]

/mp-includes/Swiftmailer/classes/Swift/Mime/Headers/ -> AbstractHeader.php (source)

   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  /**
  12   * An abstract base MIME Header.
  13   *
  14   * @author Chris Corbyn
  15   */
  16  abstract class Swift_Mime_Headers_AbstractHeader implements Swift_Mime_Header
  17  {
  18      /**
  19       * The name of this Header.
  20       *
  21       * @var string
  22       */
  23      private $_name;
  24  
  25      /**
  26       * The Grammar used for this Header.
  27       *
  28       * @var Swift_Mime_Grammar
  29       */
  30      private $_grammar;
  31  
  32      /**
  33       * The Encoder used to encode this Header.
  34       *
  35       * @var Swift_Encoder
  36       */
  37      private $_encoder;
  38  
  39      /**
  40       * The maximum length of a line in the header.
  41       *
  42       * @var int
  43       */
  44      private $_lineLength = 78;
  45  
  46      /**
  47       * The language used in this Header.
  48       *
  49       * @var string
  50       */
  51      private $_lang;
  52  
  53      /**
  54       * The character set of the text in this Header.
  55       *
  56       * @var string
  57       */
  58      private $_charset = 'utf-8';
  59  
  60      /**
  61       * The value of this Header, cached.
  62       *
  63       * @var string
  64       */
  65      private $_cachedValue = null;
  66  
  67      /**
  68       * Creates a new Header.
  69       *
  70       * @param Swift_Mime_Grammar $grammar
  71       */
  72      public function __construct(Swift_Mime_Grammar $grammar)
  73      {
  74          $this->setGrammar($grammar);
  75      }
  76  
  77      /**
  78       * Set the character set used in this Header.
  79       *
  80       * @param string $charset
  81       */
  82      public function setCharset($charset)
  83      {
  84          $this->clearCachedValueIf($charset != $this->_charset);
  85          $this->_charset = $charset;
  86          if (isset($this->_encoder)) {
  87              $this->_encoder->charsetChanged($charset);
  88          }
  89      }
  90  
  91      /**
  92       * Get the character set used in this Header.
  93       *
  94       * @return string
  95       */
  96      public function getCharset()
  97      {
  98          return $this->_charset;
  99      }
 100  
 101      /**
 102       * Set the language used in this Header.
 103       *
 104       * For example, for US English, 'en-us'.
 105       * This can be unspecified.
 106       *
 107       * @param string $lang
 108       */
 109      public function setLanguage($lang)
 110      {
 111          $this->clearCachedValueIf($this->_lang != $lang);
 112          $this->_lang = $lang;
 113      }
 114  
 115      /**
 116       * Get the language used in this Header.
 117       *
 118       * @return string
 119       */
 120      public function getLanguage()
 121      {
 122          return $this->_lang;
 123      }
 124  
 125      /**
 126       * Set the encoder used for encoding the header.
 127       *
 128       * @param Swift_Mime_HeaderEncoder $encoder
 129       */
 130      public function setEncoder(Swift_Mime_HeaderEncoder $encoder)
 131      {
 132          $this->_encoder = $encoder;
 133          $this->setCachedValue(null);
 134      }
 135  
 136      /**
 137       * Get the encoder used for encoding this Header.
 138       *
 139       * @return Swift_Mime_HeaderEncoder
 140       */
 141      public function getEncoder()
 142      {
 143          return $this->_encoder;
 144      }
 145  
 146      /**
 147       * Set the grammar used for the header.
 148       *
 149       * @param Swift_Mime_Grammar $grammar
 150       */
 151      public function setGrammar(Swift_Mime_Grammar $grammar)
 152      {
 153          $this->_grammar = $grammar;
 154          $this->setCachedValue(null);
 155      }
 156  
 157      /**
 158       * Get the grammar used for this Header.
 159       *
 160       * @return Swift_Mime_Grammar
 161       */
 162      public function getGrammar()
 163      {
 164          return $this->_grammar;
 165      }
 166  
 167      /**
 168       * Get the name of this header (e.g. charset).
 169       *
 170       * @return string
 171       */
 172      public function getFieldName()
 173      {
 174          return $this->_name;
 175      }
 176  
 177      /**
 178       * Set the maximum length of lines in the header (excluding EOL).
 179       *
 180       * @param int $lineLength
 181       */
 182      public function setMaxLineLength($lineLength)
 183      {
 184          $this->clearCachedValueIf($this->_lineLength != $lineLength);
 185          $this->_lineLength = $lineLength;
 186      }
 187  
 188      /**
 189       * Get the maximum permitted length of lines in this Header.
 190       *
 191       * @return int
 192       */
 193      public function getMaxLineLength()
 194      {
 195          return $this->_lineLength;
 196      }
 197  
 198      /**
 199       * Get this Header rendered as a RFC 2822 compliant string.
 200       *
 201       * @throws Swift_RfcComplianceException
 202       *
 203       * @return string
 204       */
 205      public function toString()
 206      {
 207          return $this->_tokensToString($this->toTokens());
 208      }
 209  
 210      /**
 211       * Returns a string representation of this object.
 212       *
 213       * @return string
 214       *
 215       * @see toString()
 216       */
 217      public function __toString()
 218      {
 219          return $this->toString();
 220      }
 221  
 222      // -- Points of extension
 223  
 224      /**
 225       * Set the name of this Header field.
 226       *
 227       * @param string $name
 228       */
 229      protected function setFieldName($name)
 230      {
 231          $this->_name = $name;
 232      }
 233  
 234      /**
 235       * Produces a compliant, formatted RFC 2822 'phrase' based on the string given.
 236       *
 237       * @param Swift_Mime_Header        $header
 238       * @param string                   $string  as displayed
 239       * @param string                   $charset of the text
 240       * @param Swift_Mime_HeaderEncoder $encoder
 241       * @param bool                     $shorten the first line to make remove for header name
 242       *
 243       * @return string
 244       */
 245      protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false)
 246      {
 247          // Treat token as exactly what was given
 248          $phraseStr = $string;
 249          // If it's not valid
 250          if (!preg_match('/^'.$this->getGrammar()->getDefinition('phrase').'$/D', $phraseStr)) {
 251              // .. but it is just ascii text, try escaping some characters
 252              // and make it a quoted-string
 253              if (preg_match('/^'.$this->getGrammar()->getDefinition('text').'*$/D', $phraseStr)) {
 254                  $phraseStr = $this->getGrammar()->escapeSpecials(
 255                      $phraseStr, array('"'), $this->getGrammar()->getSpecials()
 256                      );
 257                  $phraseStr = '"'.$phraseStr.'"';
 258              } else {
 259                  // ... otherwise it needs encoding
 260                  // Determine space remaining on line if first line
 261                  if ($shorten) {
 262                      $usedLength = strlen($header->getFieldName().': ');
 263                  } else {
 264                      $usedLength = 0;
 265                  }
 266                  $phraseStr = $this->encodeWords($header, $string, $usedLength);
 267              }
 268          }
 269  
 270          return $phraseStr;
 271      }
 272  
 273      /**
 274       * Encode needed word tokens within a string of input.
 275       *
 276       * @param Swift_Mime_Header $header
 277       * @param string            $input
 278       * @param string            $usedLength optional
 279       *
 280       * @return string
 281       */
 282      protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1)
 283      {
 284          $value = '';
 285  
 286          $tokens = $this->getEncodableWordTokens($input);
 287  
 288          foreach ($tokens as $token) {
 289              // See RFC 2822, Sect 2.2 (really 2.2 ??)
 290              if ($this->tokenNeedsEncoding($token)) {
 291                  // Don't encode starting WSP
 292                  $firstChar = substr($token, 0, 1);
 293                  switch ($firstChar) {
 294                      case ' ':
 295                      case "\t":
 296                          $value .= $firstChar;
 297                          $token = substr($token, 1);
 298                  }
 299  
 300                  if (-1 == $usedLength) {
 301                      $usedLength = strlen($header->getFieldName().': ') + strlen($value);
 302                  }
 303                  $value .= $this->getTokenAsEncodedWord($token, $usedLength);
 304  
 305                  $header->setMaxLineLength(76); // Forcefully override
 306              } else {
 307                  $value .= $token;
 308              }
 309          }
 310  
 311          return $value;
 312      }
 313  
 314      /**
 315       * Test if a token needs to be encoded or not.
 316       *
 317       * @param string $token
 318       *
 319       * @return bool
 320       */
 321      protected function tokenNeedsEncoding($token)
 322      {
 323          return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token);
 324      }
 325  
 326      /**
 327       * Splits a string into tokens in blocks of words which can be encoded quickly.
 328       *
 329       * @param string $string
 330       *
 331       * @return string[]
 332       */
 333      protected function getEncodableWordTokens($string)
 334      {
 335          $tokens = array();
 336  
 337          $encodedToken = '';
 338          // Split at all whitespace boundaries
 339          foreach (preg_split('~(?=[\t ])~', $string) as $token) {
 340              if ($this->tokenNeedsEncoding($token)) {
 341                  $encodedToken .= $token;
 342              } else {
 343                  if (strlen($encodedToken) > 0) {
 344                      $tokens[] = $encodedToken;
 345                      $encodedToken = '';
 346                  }
 347                  $tokens[] = $token;
 348              }
 349          }
 350          if (strlen($encodedToken)) {
 351              $tokens[] = $encodedToken;
 352          }
 353  
 354          return $tokens;
 355      }
 356  
 357      /**
 358       * Get a token as an encoded word for safe insertion into headers.
 359       *
 360       * @param string $token           token to encode
 361       * @param int    $firstLineOffset optional
 362       *
 363       * @return string
 364       */
 365      protected function getTokenAsEncodedWord($token, $firstLineOffset = 0)
 366      {
 367          // Adjust $firstLineOffset to account for space needed for syntax
 368          $charsetDecl = $this->_charset;
 369          if (isset($this->_lang)) {
 370              $charsetDecl .= '*'.$this->_lang;
 371          }
 372          $encodingWrapperLength = strlen(
 373              '=?'.$charsetDecl.'?'.$this->_encoder->getName().'??='
 374              );
 375  
 376          if ($firstLineOffset >= 75) {
 377              //Does this logic need to be here?
 378              $firstLineOffset = 0;
 379          }
 380  
 381          $encodedTextLines = explode("\r\n",
 382              $this->_encoder->encodeString(
 383                  $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset
 384                  )
 385          );
 386  
 387          if (strtolower($this->_charset) !== 'iso-2022-jp') {
 388              // special encoding for iso-2022-jp using mb_encode_mimeheader
 389              foreach ($encodedTextLines as $lineNum => $line) {
 390                  $encodedTextLines[$lineNum] = '=?'.$charsetDecl.
 391                      '?'.$this->_encoder->getName().
 392                      '?'.$line.'?=';
 393              }
 394          }
 395  
 396          return implode("\r\n ", $encodedTextLines);
 397      }
 398  
 399      /**
 400       * Generates tokens from the given string which include CRLF as individual tokens.
 401       *
 402       * @param string $token
 403       *
 404       * @return string[]
 405       */
 406      protected function generateTokenLines($token)
 407      {
 408          return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE);
 409      }
 410  
 411      /**
 412       * Set a value into the cache.
 413       *
 414       * @param string $value
 415       */
 416      protected function setCachedValue($value)
 417      {
 418          $this->_cachedValue = $value;
 419      }
 420  
 421      /**
 422       * Get the value in the cache.
 423       *
 424       * @return string
 425       */
 426      protected function getCachedValue()
 427      {
 428          return $this->_cachedValue;
 429      }
 430  
 431      /**
 432       * Clear the cached value if $condition is met.
 433       *
 434       * @param bool $condition
 435       */
 436      protected function clearCachedValueIf($condition)
 437      {
 438          if ($condition) {
 439              $this->setCachedValue(null);
 440          }
 441      }
 442  
 443      /**
 444       * Generate a list of all tokens in the final header.
 445       *
 446       * @param string $string The string to tokenize
 447       *
 448       * @return array An array of tokens as strings
 449       */
 450      protected function toTokens($string = null)
 451      {
 452          if (is_null($string)) {
 453              $string = $this->getFieldBody();
 454          }
 455  
 456          $tokens = array();
 457  
 458          // Generate atoms; split at all invisible boundaries followed by WSP
 459          foreach (preg_split('~(?=[ \t])~', $string) as $token) {
 460              $newTokens = $this->generateTokenLines($token);
 461              foreach ($newTokens as $newToken) {
 462                  $tokens[] = $newToken;
 463              }
 464          }
 465  
 466          return $tokens;
 467      }
 468  
 469      /**
 470       * Takes an array of tokens which appear in the header and turns them into
 471       * an RFC 2822 compliant string, adding FWSP where needed.
 472       *
 473       * @param string[] $tokens
 474       *
 475       * @return string
 476       */
 477      private function _tokensToString(array $tokens)
 478      {
 479          $lineCount = 0;
 480          $headerLines = array();
 481          $headerLines[] = $this->_name.': ';
 482          $currentLine = &$headerLines[$lineCount++];
 483  
 484          // Build all tokens back into compliant header
 485          foreach ($tokens as $i => $token) {
 486              // Line longer than specified maximum or token was just a new line
 487              if (("\r\n" == $token) ||
 488                  ($i > 0 && strlen($currentLine.$token) > $this->_lineLength)
 489                  && 0 < strlen($currentLine)) {
 490                  $headerLines[] = '';
 491                  $currentLine = &$headerLines[$lineCount++];
 492              }
 493  
 494              // Append token to the line
 495              if ("\r\n" != $token) {
 496                  $currentLine .= $token;
 497              }
 498          }
 499  
 500          // Implode with FWS (RFC 2822, 2.2.3)
 501          return implode("\r\n", $headerLines)."\r\n";
 502      }
 503  }


Generated: Thu Apr 28 18:38:52 2016 Cross-referenced by PHPXref 0.7.1