[ Index ]

MailPress 7.1

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

title

Body

[close]

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


Generated: Mon Mar 11 18:33:33 2019 Cross-referenced by PHPXref 0.7.1