Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Proxy/Linker.php
<?php

namespace XF\Proxy;

class
Linker
{
    protected
$types = [];
    protected
$secret = '';
    protected
$pather;

   
// example: proxy.php?{type}={url}&hash={hash}
   
protected $linkFormat = '';

   
/**
     * @var array[]
     */
   
protected $bypassDomains;

    public function
__construct($linkFormat, array $types, $secret, callable $pather)
    {
       
$this->linkFormat = $linkFormat;
       
$this->types = $types;
       
$this->secret = $secret;
       
$this->pather = $pather;
    }

   
/**
     * @param string $type
     * @param array  $bypass List of domains to bypass, use * as a wildcard (a value of * will bypass everything)
     */
   
public function setBypassDomains(string $type, array $bypass)
    {
       
$this->bypassDomains[$type] = array_filter($bypass, 'strlen');
    }

    public function
generate($type, $url)
    {
        if (empty(
$this->types[$type]))
        {
            return
null;
        }

        if (
$this->isUrlBypassed($type, $url))
        {
            return
null;
        }

       
$link = strtr($this->linkFormat, [
           
'{type}' => urlencode($type),
           
'{url}' => urlencode($url),
           
'{hash}' => urlencode($this->hash($url))
        ]);

        if (
$this->pather)
        {
           
$pather = $this->pather;
           
$link = $pather($link, 'base');
        }

        return
$link;
    }

    public function
generateExtended($type, $url, array $options = [])
    {
       
$url = $this->generate($type, $url);

        if (
$url === null)
        {
            return
null;
        }

        if (
$options)
        {
           
$queryString = http_build_query($options);
           
$url .= (strpos($url, '?') !== false ? '&' : '?') . $queryString;
        }

        return
$url;
    }

    public function
isTypeEnabled($type)
    {
        return !empty(
$this->types[$type]);
    }

    public function
isUrlBypassed(string $type, string $url): bool
   
{
       
$bypassDomains = $this->bypassDomains[$type] ?? null;
        if (!
$bypassDomains)
        {
            return
false;
        }

       
$urlParsed = parse_url($url);
        if (!
$urlParsed)
        {
            return
false;
        }

        if (!isset(
$urlParsed['host'], $urlParsed['scheme']))
        {
            return
false;
        }

        if (
strtolower($urlParsed['scheme']) !== 'https')
        {
           
// always proxy non-https links
           
return false;
        }

       
$host = strtolower($urlParsed['host']);

        foreach (
$bypassDomains AS $bypassDomain)
        {
            if (
$bypassDomain == '*')
            {
                return
true;
            }

            if (
$bypassDomain[0] != '/')
            {
               
$regex = '#(^|\.)' . preg_quote($bypassDomain, '#') . '$#i';
            }
            else
            {
                if (
preg_match('/\W[\s\w]*e[\s\w]*$/', $bypassDomain))
                {
                   
// can't run a /e regex
                   
continue;
                }

               
$regex = $bypassDomain;
            }

            try
            {
                if (
preg_match($regex, $host))
                {
                    return
true;
                }
            }
            catch (\
ErrorException $e) {}
        }

        return
false;
    }

    public function
verifyHash($url, $hash)
    {
        return
$this->hash($url) === $hash;
    }

    public function
hash($url)
    {
        return
hash_hmac('md5', $url, $this->secret);
    }
}