vendor/contao/core-bundle/src/Resources/contao/library/Contao/Environment.php line 529

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. /**
  11.  * Reads the environment variables
  12.  *
  13.  * The class returns the environment variables (which are stored in the PHP
  14.  * $_SERVER array) independent of the operating system.
  15.  *
  16.  * Usage:
  17.  *
  18.  *     echo Environment::get('scriptName');
  19.  *     echo Environment::get('requestUri');
  20.  */
  21. class Environment
  22. {
  23.     /**
  24.      * Object instance (Singleton)
  25.      * @var Environment
  26.      */
  27.     protected static $objInstance;
  28.     /**
  29.      * The SAPI name
  30.      * @var string
  31.      */
  32.     protected static $strSapi = \PHP_SAPI;
  33.     /**
  34.      * Cache
  35.      * @var array
  36.      */
  37.     protected static $arrCache = array();
  38.     /**
  39.      * Return an environment variable
  40.      *
  41.      * @param string $strKey The variable name
  42.      *
  43.      * @return mixed The variable value
  44.      */
  45.     public static function get($strKey)
  46.     {
  47.         if (isset(static::$arrCache[$strKey]))
  48.         {
  49.             return static::$arrCache[$strKey];
  50.         }
  51.         if (\in_array($strKeyget_class_methods(self::class)))
  52.         {
  53.             static::$arrCache[$strKey] = static::$strKey();
  54.         }
  55.         else
  56.         {
  57.             $arrChunks preg_split('/([A-Z][a-z]*)/'$strKey, -1PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
  58.             $strServerKey strtoupper(implode('_'$arrChunks));
  59.             static::$arrCache[$strKey] = $_SERVER[$strServerKey];
  60.         }
  61.         return static::$arrCache[$strKey];
  62.     }
  63.     /**
  64.      * Set an environment variable
  65.      *
  66.      * @param string $strKey   The variable name
  67.      * @param mixed  $varValue The variable value
  68.      */
  69.     public static function set($strKey$varValue)
  70.     {
  71.         static::$arrCache[$strKey] = $varValue;
  72.     }
  73.     /**
  74.      * Reset the internal cache
  75.      */
  76.     public static function reset()
  77.     {
  78.         static::$arrCache = array();
  79.     }
  80.     /**
  81.      * Return the absolute path to the script (e.g. /home/www/html/website/index.php)
  82.      *
  83.      * @return string The absolute path to the script
  84.      */
  85.     protected static function scriptFilename()
  86.     {
  87.         return str_replace('//''/'strtr((static::$strSapi == 'cgi' || static::$strSapi == 'isapi' || static::$strSapi == 'cgi-fcgi' || static::$strSapi == 'fpm-fcgi') && ($_SERVER['ORIG_PATH_TRANSLATED'] ?? $_SERVER['PATH_TRANSLATED']) ? ($_SERVER['ORIG_PATH_TRANSLATED'] ?? $_SERVER['PATH_TRANSLATED']) : ($_SERVER['ORIG_SCRIPT_FILENAME'] ?? $_SERVER['SCRIPT_FILENAME']), '\\''/'));
  88.     }
  89.     /**
  90.      * Return the relative path to the script (e.g. /website/index.php)
  91.      *
  92.      * @return string The relative path to the script
  93.      */
  94.     protected static function scriptName()
  95.     {
  96.         $request System::getContainer()->get('request_stack')->getCurrentRequest();
  97.         if ($request === null)
  98.         {
  99.             return $_SERVER['ORIG_SCRIPT_NAME'] ?? $_SERVER['SCRIPT_NAME'];
  100.         }
  101.         return $request->getScriptName();
  102.     }
  103.     /**
  104.      * Alias for scriptName()
  105.      *
  106.      * @return string The script name
  107.      */
  108.     protected static function phpSelf()
  109.     {
  110.         return static::scriptName();
  111.     }
  112.     /**
  113.      * Return the document root (e.g. /home/www/user/)
  114.      *
  115.      * Calculated as SCRIPT_FILENAME minus SCRIPT_NAME as some CGI versions
  116.      * and mod-rewrite rules might return an incorrect DOCUMENT_ROOT.
  117.      *
  118.      * @return string The document root
  119.      */
  120.     protected static function documentRoot()
  121.     {
  122.         $strDocumentRoot '';
  123.         $arrUriSegments = array();
  124.         $scriptName = static::get('scriptName');
  125.         $scriptFilename = static::get('scriptFilename');
  126.         // Fallback to DOCUMENT_ROOT if SCRIPT_FILENAME and SCRIPT_NAME point to different files
  127.         if (basename($scriptName) != basename($scriptFilename))
  128.         {
  129.             return str_replace('//''/'strtr(realpath($_SERVER['DOCUMENT_ROOT']), '\\''/'));
  130.         }
  131.         if (=== strncmp($scriptFilename'/'1))
  132.         {
  133.             $strDocumentRoot '/';
  134.         }
  135.         $arrSnSegments explode('/'strrev($scriptName));
  136.         $arrSfnSegments explode('/'strrev($scriptFilename));
  137.         foreach ($arrSfnSegments as $k=>$v)
  138.         {
  139.             if (@$arrSnSegments[$k] != $v)
  140.             {
  141.                 $arrUriSegments[] = $v;
  142.             }
  143.         }
  144.         $strDocumentRoot .= strrev(implode('/'$arrUriSegments));
  145.         if (\strlen($strDocumentRoot) < 2)
  146.         {
  147.             $strDocumentRoot substr($scriptFilename0, -(\strlen($strDocumentRoot) + 1));
  148.         }
  149.         return str_replace('//''/'strtr(realpath($strDocumentRoot), '\\''/'));
  150.     }
  151.     /**
  152.      * Return the query string (e.g. id=2)
  153.      *
  154.      * @return string The query string
  155.      */
  156.     protected static function queryString()
  157.     {
  158.         if (!isset($_SERVER['QUERY_STRING']))
  159.         {
  160.             return '';
  161.         }
  162.         return static::encodeRequestString($_SERVER['QUERY_STRING']);
  163.     }
  164.     /**
  165.      * Return the request URI [path]?[query] (e.g. /contao/index.php?id=2)
  166.      *
  167.      * @return string The request URI
  168.      */
  169.     protected static function requestUri()
  170.     {
  171.         if (!empty($_SERVER['REQUEST_URI']))
  172.         {
  173.             $arrComponents parse_url($_SERVER['REQUEST_URI']);
  174.             if ($arrComponents === false)
  175.             {
  176.                 $strRequest $_SERVER['REQUEST_URI'];
  177.             }
  178.             else
  179.             {
  180.                 $strRequest $arrComponents['path'] . (isset($arrComponents['query']) ? '?' $arrComponents['query'] : '');
  181.             }
  182.         }
  183.         else
  184.         {
  185.             $strRequest '/' preg_replace('/^\//''', static::get('scriptName')) . (!empty($_SERVER['QUERY_STRING']) ? '?' $_SERVER['QUERY_STRING'] : '');
  186.         }
  187.         return static::encodeRequestString($strRequest);
  188.     }
  189.     /**
  190.      * Return the first eight accepted languages as array
  191.      *
  192.      * @return array The languages array
  193.      */
  194.     protected static function httpAcceptLanguage()
  195.     {
  196.         $arrAccepted = array();
  197.         $arrLanguages = array();
  198.         // The implementation differs from the original implementation and also works with .jp browsers
  199.         preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i'$_SERVER['HTTP_ACCEPT_LANGUAGE'], $arrAccepted);
  200.         // Remove all invalid locales
  201.         foreach ($arrAccepted[1] as $v)
  202.         {
  203.             $chunks explode('-'$v);
  204.             // Language plus dialect, e.g. en-US or fr-FR
  205.             if (isset($chunks[1]))
  206.             {
  207.                 $locale $chunks[0] . '-' strtoupper($chunks[1]);
  208.                 if (preg_match('/^[a-z]{2}(-[A-Z]{2})?$/'$locale))
  209.                 {
  210.                     $arrLanguages[] = $locale;
  211.                 }
  212.             }
  213.             $locale $chunks[0];
  214.             // Language only, e.g. en or fr (see #29)
  215.             if (preg_match('/^[a-z]{2}$/'$locale))
  216.             {
  217.                 $arrLanguages[] = $locale;
  218.             }
  219.         }
  220.         return \array_slice(array_unique($arrLanguages), 08);
  221.     }
  222.     /**
  223.      * Return accepted encoding types as array
  224.      *
  225.      * @return array The encoding types array
  226.      */
  227.     protected static function httpAcceptEncoding()
  228.     {
  229.         return array_values(array_unique(explode(','strtolower($_SERVER['HTTP_ACCEPT_ENCODING']))));
  230.     }
  231.     /**
  232.      * Return the user agent as string
  233.      *
  234.      * @return string The user agent string
  235.      */
  236.     protected static function httpUserAgent()
  237.     {
  238.         $ua strip_tags($_SERVER['HTTP_USER_AGENT']);
  239.         $ua preg_replace('/javascript|vbscri?pt|script|applet|alert|document|write|cookie/i'''$ua);
  240.         return substr($ua0255);
  241.     }
  242.     /**
  243.      * Return the HTTP Host
  244.      *
  245.      * @return string The host name
  246.      */
  247.     protected static function httpHost()
  248.     {
  249.         if (!empty($_SERVER['HTTP_HOST']))
  250.         {
  251.             $host $_SERVER['HTTP_HOST'];
  252.         }
  253.         else
  254.         {
  255.             $host $_SERVER['SERVER_NAME'] ?? null;
  256.             if (($_SERVER['SERVER_PORT'] ?? 80) != 80)
  257.             {
  258.                 $host .= ':' $_SERVER['SERVER_PORT'];
  259.             }
  260.         }
  261.         return preg_replace('/[^A-Za-z0-9[\].:_-]/'''$host);
  262.     }
  263.     /**
  264.      * Return the HTTP X-Forwarded-Host
  265.      *
  266.      * @return string The name of the X-Forwarded-Host
  267.      */
  268.     protected static function httpXForwardedHost()
  269.     {
  270.         if (!isset($_SERVER['HTTP_X_FORWARDED_HOST']))
  271.         {
  272.             return '';
  273.         }
  274.         return preg_replace('/[^A-Za-z0-9[\].:-]/'''$_SERVER['HTTP_X_FORWARDED_HOST']);
  275.     }
  276.     /**
  277.      * Return true if the current page was requested via an SSL connection
  278.      *
  279.      * @return boolean True if SSL is enabled
  280.      */
  281.     protected static function ssl()
  282.     {
  283.         $request System::getContainer()->get('request_stack')->getCurrentRequest();
  284.         if ($request === null)
  285.         {
  286.             return false;
  287.         }
  288.         return $request->isSecure();
  289.     }
  290.     /**
  291.      * Return the current URL without path or query string
  292.      *
  293.      * @return string The URL
  294.      */
  295.     protected static function url()
  296.     {
  297.         return (static::get('ssl') ? 'https://' 'http://') . static::get('httpHost');
  298.     }
  299.     /**
  300.      * Return the current URL with path or query string
  301.      *
  302.      * @return string The URL
  303.      */
  304.     protected static function uri()
  305.     {
  306.         return static::get('url') . static::get('requestUri');
  307.     }
  308.     /**
  309.      * Return the real REMOTE_ADDR even if a proxy server is used
  310.      *
  311.      * @return string The IP address of the client
  312.      */
  313.     protected static function ip()
  314.     {
  315.         $request System::getContainer()->get('request_stack')->getCurrentRequest();
  316.         if ($request === null)
  317.         {
  318.             return '';
  319.         }
  320.         return $request->getClientIp();
  321.     }
  322.     /**
  323.      * Return the SERVER_ADDR
  324.      *
  325.      * @return string The IP address of the server
  326.      */
  327.     protected static function server()
  328.     {
  329.         $strServer = !empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['LOCAL_ADDR'];
  330.         // Special workaround for Strato users
  331.         if (empty($strServer))
  332.         {
  333.             $strServer = @gethostbyname($_SERVER['SERVER_NAME']);
  334.         }
  335.         return $strServer;
  336.     }
  337.     /**
  338.      * Return the relative path to the base directory (e.g. /path)
  339.      *
  340.      * @return string The relative path to the installation
  341.      */
  342.     protected static function path()
  343.     {
  344.         $request System::getContainer()->get('request_stack')->getCurrentRequest();
  345.         if ($request === null)
  346.         {
  347.             return '';
  348.         }
  349.         return $request->getBasePath();
  350.     }
  351.     /**
  352.      * Return the relative path to the script (e.g. index.php)
  353.      *
  354.      * @return string The relative path to the script
  355.      */
  356.     protected static function script()
  357.     {
  358.         return preg_replace('/^' preg_quote(static::get('path'), '/') . '\/?/''', static::get('scriptName'));
  359.     }
  360.     /**
  361.      * Return the relative path to the script and include the request (e.g. index.php?id=2)
  362.      *
  363.      * @return string The relative path to the script including the request string
  364.      */
  365.     protected static function request()
  366.     {
  367.         return preg_replace('/^' preg_quote(static::get('path'), '/') . '\/?/''', static::get('requestUri'));
  368.     }
  369.     /**
  370.      * Return the request string without the script name (e.g. en/news.html)
  371.      *
  372.      * @return string The base URL
  373.      */
  374.     protected static function relativeRequest()
  375.     {
  376.         return preg_replace('/^' preg_quote(static::get('script'), '/') . '\/?/''', static::get('request'));
  377.     }
  378.     /**
  379.      * Return the request string without the index.php fragment
  380.      *
  381.      * @return string The request string without the index.php fragment
  382.      */
  383.     protected static function indexFreeRequest()
  384.     {
  385.         $strRequest = static::get('request');
  386.         if ($strRequest == static::get('script'))
  387.         {
  388.             return '';
  389.         }
  390.         return $strRequest;
  391.     }
  392.     /**
  393.      * Return the URL and path that can be used in a <base> tag
  394.      *
  395.      * @return string The base URL
  396.      */
  397.     protected static function base()
  398.     {
  399.         return static::get('url') . static::get('path') . '/';
  400.     }
  401.     /**
  402.      * Return the host name
  403.      *
  404.      * @return string The host name
  405.      */
  406.     protected static function host()
  407.     {
  408.         return preg_replace('/:\d+$/''', static::get('httpHost'));
  409.     }
  410.     /**
  411.      * Return true on Ajax requests
  412.      *
  413.      * @return boolean True if it is an Ajax request
  414.      */
  415.     protected static function isAjaxRequest()
  416.     {
  417.         if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']))
  418.         {
  419.             return false;
  420.         }
  421.         return $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
  422.     }
  423.     /**
  424.      * Return the operating system and the browser name and version
  425.      *
  426.      * @return object The agent information
  427.      *
  428.      * @deprecated Deprecated since Contao 4.13, to be removed in Contao 5.0.
  429.      */
  430.     protected static function agent()
  431.     {
  432.         trigger_deprecation('contao/core-bundle''4.13''Using "%s::get(\'agent\')" has been deprecated and will no longer work in Contao 5.0.'__CLASS__);
  433.         $ua = static::get('httpUserAgent');
  434.         $return = new \stdClass();
  435.         $return->string $ua;
  436.         $os 'unknown';
  437.         $mobile false;
  438.         $browser 'other';
  439.         $shorty '';
  440.         $version '';
  441.         $engine '';
  442.         // Operating system
  443.         foreach (Config::get('os') as $k=>$v)
  444.         {
  445.             if (stripos($ua$k) !== false)
  446.             {
  447.                 $os $v['os'];
  448.                 $mobile $v['mobile'];
  449.                 break;
  450.             }
  451.         }
  452.         $return->os $os;
  453.         // Browser and version
  454.         foreach (Config::get('browser') as $k=>$v)
  455.         {
  456.             if (stripos($ua$k) !== false)
  457.             {
  458.                 $browser $v['browser'];
  459.                 $shorty  $v['shorty'];
  460.                 $version preg_replace($v['version'], '$1'$ua);
  461.                 $engine  $v['engine'];
  462.                 break;
  463.             }
  464.         }
  465.         $versions explode('.'$version);
  466.         $version  $versions[0];
  467.         $return->class $os ' ' $browser ' ' $engine;
  468.         // Add the version number if available
  469.         if ($version)
  470.         {
  471.             $return->class .= ' ' $shorty $version;
  472.         }
  473.         // Android tablets are not mobile (see #4150 and #5869)
  474.         if ($os == 'android' && $engine != 'presto' && stripos($ua'mobile') === false)
  475.         {
  476.             $mobile false;
  477.         }
  478.         // Mark mobile devices
  479.         if ($mobile)
  480.         {
  481.             $return->class .= ' mobile';
  482.         }
  483.         $return->browser  $browser;
  484.         $return->shorty   $shorty;
  485.         $return->version  $version;
  486.         $return->engine   $engine;
  487.         $return->versions $versions;
  488.         $return->mobile   $mobile;
  489.         return $return;
  490.     }
  491.     /**
  492.      * Encode a request string preserving certain reserved characters
  493.      *
  494.      * @param string $strRequest The request string
  495.      *
  496.      * @return string The encoded request string
  497.      */
  498.     protected static function encodeRequestString($strRequest)
  499.     {
  500.         return preg_replace_callback('/[^A-Za-z0-9\-_.~&=+,\/?%\[\]]+/', static function ($matches) { return rawurlencode($matches[0]); }, $strRequest);
  501.     }
  502.     /**
  503.      * Prevent direct instantiation (Singleton)
  504.      *
  505.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  506.      *             The Environment class is now static.
  507.      */
  508.     protected function __construct()
  509.     {
  510.     }
  511.     /**
  512.      * Prevent cloning of the object (Singleton)
  513.      *
  514.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  515.      *             The Environment class is now static.
  516.      */
  517.     final public function __clone()
  518.     {
  519.     }
  520.     /**
  521.      * Return an environment variable
  522.      *
  523.      * @param string $strKey The variable name
  524.      *
  525.      * @return string The variable value
  526.      *
  527.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  528.      *             Use Environment::get() instead.
  529.      */
  530.     public function __get($strKey)
  531.     {
  532.         return static::get($strKey);
  533.     }
  534.     /**
  535.      * Set an environment variable
  536.      *
  537.      * @param string $strKey   The variable name
  538.      * @param mixed  $varValue The variable value
  539.      *
  540.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  541.      *             Use Environment::set() instead.
  542.      */
  543.     public function __set($strKey$varValue)
  544.     {
  545.         static::set($strKey$varValue);
  546.     }
  547.     /**
  548.      * Return the object instance (Singleton)
  549.      *
  550.      * @return Environment The object instance
  551.      *
  552.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  553.      *             The Environment class is now static.
  554.      */
  555.     public static function getInstance()
  556.     {
  557.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\Environment::getInstance()" has been deprecated and will no longer work in Contao 5.0. The "Contao\Environment" class is now static.');
  558.         if (static::$objInstance === null)
  559.         {
  560.             static::$objInstance = new static();
  561.         }
  562.         return static::$objInstance;
  563.     }
  564. }
  565. class_alias(Environment::class, 'Environment');