Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. ParameterizedHeader.php

class ParameterizedHeader

@author Chris Corbyn

Hierarchy

  • class \Symfony\Component\Mime\Header\AbstractHeader implements \Symfony\Component\Mime\Header\HeaderInterface
    • class \Symfony\Component\Mime\Header\UnstructuredHeader extends \Symfony\Component\Mime\Header\AbstractHeader
      • class \Symfony\Component\Mime\Header\ParameterizedHeader extends \Symfony\Component\Mime\Header\UnstructuredHeader

Expanded class hierarchy of ParameterizedHeader

File

vendor/symfony/mime/Header/ParameterizedHeader.php, line 19

Namespace

Symfony\Component\Mime\Header
View source
final class ParameterizedHeader extends UnstructuredHeader {
    
    /**
     * RFC 2231's definition of a token.
     *
     * @var string
     */
    public const TOKEN_REGEX = '(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2E\\x30-\\x39\\x41-\\x5A\\x5E-\\x7E]+)';
    private ?Rfc2231Encoder $encoder = null;
    private array $parameters = [];
    public function __construct(string $name, string $value, array $parameters = []) {
        parent::__construct($name, $value);
        foreach ($parameters as $k => $v) {
            $this->setParameter($k, $v);
        }
        if ('content-type' !== strtolower($name)) {
            $this->encoder = new Rfc2231Encoder();
        }
    }
    public function setParameter(string $parameter, ?string $value) : void {
        $this->setParameters(array_merge($this->getParameters(), [
            $parameter => $value,
        ]));
    }
    public function getParameter(string $parameter) : string {
        return $this->getParameters()[$parameter] ?? '';
    }
    
    /**
     * @param string[] $parameters
     */
    public function setParameters(array $parameters) : void {
        $this->parameters = $parameters;
    }
    
    /**
     * @return string[]
     */
    public function getParameters() : array {
        return $this->parameters;
    }
    public function getBodyAsString() : string {
        $body = parent::getBodyAsString();
        foreach ($this->parameters as $name => $value) {
            if (null !== $value) {
                $body .= '; ' . $this->createParameter($name, $value);
            }
        }
        return $body;
    }
    
    /**
     * Generate a list of all tokens in the final header.
     *
     * This doesn't need to be overridden in theory, but it is for implementation
     * reasons to prevent potential breakage of attributes.
     */
    protected function toTokens(?string $string = null) : array {
        $tokens = parent::toTokens(parent::getBodyAsString());
        // Try creating any parameters
        foreach ($this->parameters as $name => $value) {
            if (null !== $value) {
                // Add the semi-colon separator
                $tokens[\count($tokens) - 1] .= ';';
                $tokens = array_merge($tokens, $this->generateTokenLines(' ' . $this->createParameter($name, $value)));
            }
        }
        return $tokens;
    }
    
    /**
     * Render an RFC 2047 compliant header parameter from the $name and $value.
     */
    private function createParameter(string $name, string $value) : string {
        $origValue = $value;
        $encoded = false;
        // Allow room for parameter name, indices, "=" and DQUOTEs
        $maxValueLength = $this->getMaxLineLength() - \strlen($name . '=*N"";') - 1;
        $firstLineOffset = 0;
        // If it's not already a valid parameter value...
        if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
            // TODO: text, or something else??
            // ... and it's not ascii
            if (!preg_match('/^[\\x00-\\x08\\x0B\\x0C\\x0E-\\x7F]*$/D', $value)) {
                $encoded = true;
                // Allow space for the indices, charset and language
                $maxValueLength = $this->getMaxLineLength() - \strlen($name . '*N*="";') - 1;
                $firstLineOffset = \strlen($this->getCharset() . "'" . $this->getLanguage() . "'");
            }
            if (\in_array($name, [
                'name',
                'filename',
            ], true) && 'form-data' === $this->getValue() && 'content-disposition' === strtolower($this->getName()) && preg_match('//u', $value)) {
                // WHATWG HTML living standard 4.10.21.8 2 specifies:
                // For field names and filenames for file fields, the result of the
                // encoding in the previous bullet point must be escaped by replacing
                // any 0x0A (LF) bytes with the byte sequence `%0A`, 0x0D (CR) with `%0D`
                // and 0x22 (") with `%22`.
                // The user agent must not perform any other escapes.
                $value = str_replace([
                    '"',
                    "\r",
                    "\n",
                ], [
                    '%22',
                    '%0D',
                    '%0A',
                ], $value);
                if (\strlen($value) <= $maxValueLength) {
                    return $name . '="' . $value . '"';
                }
                $value = $origValue;
            }
        }
        // Encode if we need to
        if ($encoded || \strlen($value) > $maxValueLength) {
            if (null !== $this->encoder) {
                $value = $this->encoder
                    ->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength);
            }
            else {
                // We have to go against RFC 2183/2231 in some areas for interoperability
                $value = $this->getTokenAsEncodedWord($origValue);
                $encoded = false;
            }
        }
        $valueLines = $this->encoder ? explode("\r\n", $value) : [
            $value,
        ];
        // Need to add indices
        if (\count($valueLines) > 1) {
            $paramLines = [];
            foreach ($valueLines as $i => $line) {
                $paramLines[] = $name . '*' . $i . $this->getEndOfParameterValue($line, true, 0 === $i);
            }
            return implode(";\r\n ", $paramLines);
        }
        return $name . $this->getEndOfParameterValue($valueLines[0], $encoded, true);
    }
    
    /**
     * Returns the parameter value from the "=" and beyond.
     *
     * @param string $value to append
     */
    private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false) : string {
        $forceHttpQuoting = 'form-data' === $this->getValue() && 'content-disposition' === strtolower($this->getName());
        if ($forceHttpQuoting || !preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
            $value = '"' . $value . '"';
        }
        $prepend = '=';
        if ($encoded) {
            $prepend = '*=';
            if ($firstLine) {
                $prepend = '*=' . $this->getCharset() . "'" . $this->getLanguage() . "'";
            }
        }
        return $prepend . $value;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
AbstractHeader::$charset private property
AbstractHeader::$lang private property
AbstractHeader::$lineLength private property
AbstractHeader::$name private property
AbstractHeader::createPhrase protected function Produces a compliant, formatted RFC 2822 &#039;phrase&#039; based on the string given.
AbstractHeader::encodeWords protected function Encode needed word tokens within a string of input.
AbstractHeader::generateTokenLines protected function Generates tokens from the given string which include CRLF as individual tokens.
AbstractHeader::getCharset public function Overrides HeaderInterface::getCharset
AbstractHeader::getEncodableWordTokens protected function Splits a string into tokens in blocks of words which can be encoded quickly.
AbstractHeader::getLanguage public function Overrides HeaderInterface::getLanguage
AbstractHeader::getMaxLineLength public function Overrides HeaderInterface::getMaxLineLength
AbstractHeader::getName public function Overrides HeaderInterface::getName
AbstractHeader::getTokenAsEncodedWord protected function Get a token as an encoded word for safe insertion into headers.
AbstractHeader::PHRASE_PATTERN public constant
AbstractHeader::setCharset public function Overrides HeaderInterface::setCharset
AbstractHeader::setLanguage public function Set the language used in this Header. Overrides HeaderInterface::setLanguage
AbstractHeader::setMaxLineLength public function Overrides HeaderInterface::setMaxLineLength
AbstractHeader::tokenNeedsEncoding protected function 2
AbstractHeader::tokensToString private function Takes an array of tokens which appear in the header and turns them into
an RFC 2822 compliant string, adding FWSP where needed.
AbstractHeader::toString public function Gets this Header rendered as a compliant string. Overrides HeaderInterface::toString
ParameterizedHeader::$encoder private property Overrides AbstractHeader::$encoder
ParameterizedHeader::$parameters private property
ParameterizedHeader::createParameter private function Render an RFC 2047 compliant header parameter from the $name and $value.
ParameterizedHeader::getBodyAsString public function Get the value of this header prepared for rendering. Overrides UnstructuredHeader::getBodyAsString
ParameterizedHeader::getEndOfParameterValue private function Returns the parameter value from the &quot;=&quot; and beyond.
ParameterizedHeader::getParameter public function
ParameterizedHeader::getParameters public function
ParameterizedHeader::setParameter public function
ParameterizedHeader::setParameters public function
ParameterizedHeader::TOKEN_REGEX public constant RFC 2231&#039;s definition of a token.
ParameterizedHeader::toTokens protected function Generate a list of all tokens in the final header. Overrides AbstractHeader::toTokens
ParameterizedHeader::__construct public function Overrides UnstructuredHeader::__construct
UnstructuredHeader::$value private property
UnstructuredHeader::getBody public function Gets the body. Overrides HeaderInterface::getBody
UnstructuredHeader::getValue public function Get the (unencoded) value of this header.
UnstructuredHeader::setBody public function Overrides HeaderInterface::setBody
UnstructuredHeader::setValue public function Set the (unencoded) value of this header.

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal