Вход Регистрация
Файл: vendor/symfony/http-foundation/HeaderUtils.php
Строк: 280
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentHttpFoundation;

/**
 * HTTP header utility functions.
 *
 * @author Christian Schmidt <github@chsc.dk>
 */
class HeaderUtils
{
    public const 
DISPOSITION_ATTACHMENT 'attachment';
    public const 
DISPOSITION_INLINE 'inline';

    
/**
     * This class should not be instantiated.
     */
    
private function __construct()
    {
    }

    
/**
     * Splits an HTTP header by one or more separators.
     *
     * Example:
     *
     *     HeaderUtils::split('da, en-gb;q=0.8', ',;')
     *     // => ['da'], ['en-gb', 'q=0.8']]
     *
     * @param string $separators List of characters to split on, ordered by
     *                           precedence, e.g. ',', ';=', or ',;='
     *
     * @return array Nested array with as many levels as there are characters in
     *               $separators
     */
    
public static function split(string $headerstring $separators): array
    {
        if (
'' === $separators) {
            throw new 
InvalidArgumentException('At least one separator must be specified.');
        }

        
$quotedSeparators preg_quote($separators'/');

        
preg_match_all('
            /
                (?!s)
                    (?:
                        # quoted-string
                        "(?:[^"\\]|\\.)*(?:"|\\|$)
                    |
                        # token
                        [^"'
.$quotedSeparators.']+
                    )+
                (?<!s)
            |
                # separator
                s*
                (?<separator>['
.$quotedSeparators.'])
                s*
            /x'
trim($header), $matchesPREG_SET_ORDER);

        return 
self::groupParts($matches$separators);
    }

    
/**
     * Combines an array of arrays into one associative array.
     *
     * Each of the nested arrays should have one or two elements. The first
     * value will be used as the keys in the associative array, and the second
     * will be used as the values, or true if the nested array only contains one
     * element. Array keys are lowercased.
     *
     * Example:
     *
     *     HeaderUtils::combine([['foo', 'abc'], ['bar']])
     *     // => ['foo' => 'abc', 'bar' => true]
     */
    
public static function combine(array $parts): array
    {
        
$assoc = [];
        foreach (
$parts as $part) {
            
$name strtolower($part[0]);
            
$value $part[1] ?? true;
            
$assoc[$name] = $value;
        }

        return 
$assoc;
    }

    
/**
     * Joins an associative array into a string for use in an HTTP header.
     *
     * The key and value of each entry are joined with '=', and all entries
     * are joined with the specified separator and an additional space (for
     * readability). Values are quoted if necessary.
     *
     * Example:
     *
     *     HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',')
     *     // => 'foo=abc, bar, baz="a b c"'
     */
    
public static function toString(array $assocstring $separator): string
    
{
        
$parts = [];
        foreach (
$assoc as $name => $value) {
            if (
true === $value) {
                
$parts[] = $name;
            } else {
                
$parts[] = $name.'='.self::quote($value);
            }
        }

        return 
implode($separator.' '$parts);
    }

    
/**
     * Encodes a string as a quoted string, if necessary.
     *
     * If a string contains characters not allowed by the "token" construct in
     * the HTTP specification, it is backslash-escaped and enclosed in quotes
     * to match the "quoted-string" construct.
     */
    
public static function quote(string $s): string
    
{
        if (
preg_match('/^[a-z0-9!#$%&'*.^_`|~-]+$/i', $s)) {
            return 
$s;
        }

        return '"'.addcslashes(
$s, '"\"').'"';
    }

    /**
     * Decodes a quoted string.
     *
     * If passed an unquoted string that matches the "token" construct (as
     * defined in the HTTP specification), it is passed through verbatim.
     */
    public static function unquote(string 
$s): string
    {
        return preg_replace('/\\(.)|"/', '$1', 
$s);
    }

    /**
     * Generates an HTTP Content-Disposition field-value.
     *
     * @param string 
$disposition      One of "inline" or "attachment"
     * @param string 
$filename         A unicode string
     * @param string 
$filenameFallback A string containing only ASCII characters that
     *                                 is semantically equivalent to 
$filename. If the filename is already ASCII,
     *                                 it can be omitted, or just copied from 
$filename
     *
     * @throws InvalidArgumentException
     *
     * @see RFC 6266
     */
    public static function makeDisposition(string 
$disposition, string $filename, string $filenameFallback = ''): string
    {
        if (!in_array(
$disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
            throw new InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
        }

        if ('' === 
$filenameFallback) {
            
$filenameFallback = $filename;
        }

        // filenameFallback is not ASCII.
        if (!preg_match('/^[x20-x7e]*$/', 
$filenameFallback)) {
            throw new InvalidArgumentException('The filename fallback must only contain ASCII characters.');
        }

        // percent characters aren't safe in fallback.
        if (str_contains(
$filenameFallback, '%')) {
            throw new InvalidArgumentException('The filename fallback cannot contain the "%" character.');
        }

        // path separators aren't allowed in either.
        if (str_contains(
$filename, '/') || str_contains($filename, '\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\')) {
            throw new InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\" characters.');
        }

        
$params = ['filename' => $filenameFallback];
        if (
$filename !== $filenameFallback) {
            
$params['filename*'] = "utf-8''".rawurlencode($filename);
        }

        return 
$disposition.'; '.self::toString($params, ';');
    }

    /**
     * Like parse_str(), but preserves dots in variable names.
     */
    public static function parseQuery(string 
$query, bool $ignoreBrackets = false, string $separator = '&'): array
    {
        
$q = [];

        foreach (explode(
$separator$query) as $v) {
            if (false !== 
$i = strpos($v, "")) {
                
$v = substr($v, 0, $i);
            }

            if (false === 
$i = strpos($v, '=')) {
                
$k = urldecode($v);
                
$v = '';
            } else {
                
$k = urldecode(substr($v, 0, $i));
                
$v = substr($v$i);
            }

            if (false !== 
$i = strpos($k, "")) {
                
$k = substr($k, 0, $i);
            }

            
$k = ltrim($k, ' ');

            if (
$ignoreBrackets) {
                
$q[$k][] = urldecode(substr($v, 1));

                continue;
            }

            if (false === 
$i = strpos($k, '[')) {
                
$q[] = bin2hex($k).$v;
            } else {
                
$q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k$i)).$v;
            }
        }

        if (
$ignoreBrackets) {
            return 
$q;
        }

        parse_str(implode('&', 
$q), $q);

        
$query = [];

        foreach (
$q as $k => $v) {
            if (false !== 
$i = strpos($k, '_')) {
                
$query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v;
            } else {
                
$query[hex2bin($k)] = $v;
            }
        }

        return 
$query;
    }

    private static function groupParts(array 
$matches, string $separators, bool $first = true): array
    {
        
$separator = $separators[0];
        
$separators = substr($separators, 1) ?: '';
        
$i = 0;

        if ('' === 
$separators && !$first) {
            
$parts = [''];

            foreach (
$matches as $match) {
                if (!
$i && isset($match['separator'])) {
                    
$i = 1;
                    
$parts[1] = '';
                } else {
                    
$parts[$i] .= self::unquote($match[0]);
                }
            }

            return 
$parts;
        }

        
$parts = [];
        
$partMatches = [];

        foreach (
$matches as $match) {
            if ((
$match['separator'] ?? null) === $separator) {
                ++
$i;
            } else {
                
$partMatches[$i][] = $match;
            }
        }

        foreach (
$partMatches as $matches) {
            if ('' === 
$separators && '' !== $unquoted = self::unquote($matches[0][0])) {
                
$parts[] = $unquoted;
            } elseif (
$groupedParts = self::groupParts($matches$separators, false)) {
                
$parts[] = $groupedParts;
            }
        }

        return 
$parts;
    }
}
Онлайн: 0
Реклама