Changeset View
Changeset View
Standalone View
Standalone View
support/startup/PhabricatorStartup.php
| Show All 29 Lines | |||||
| * all of the tracked buckets. | * all of the tracked buckets. | ||||
| * | * | ||||
| * @task info Accessing Request Information | * @task info Accessing Request Information | ||||
| * @task hook Startup Hooks | * @task hook Startup Hooks | ||||
| * @task apocalypse In Case Of Apocalypse | * @task apocalypse In Case Of Apocalypse | ||||
| * @task validation Validation | * @task validation Validation | ||||
| * @task ratelimit Rate Limiting | * @task ratelimit Rate Limiting | ||||
| * @task phases Startup Phase Timers | * @task phases Startup Phase Timers | ||||
| * @task request-path Request Path | |||||
| */ | */ | ||||
| final class PhabricatorStartup { | final class PhabricatorStartup { | ||||
| private static $startTime; | private static $startTime; | ||||
| private static $debugTimeLimit; | private static $debugTimeLimit; | ||||
| private static $accessLog; | private static $accessLog; | ||||
| private static $capturingOutput; | private static $capturingOutput; | ||||
| private static $rawInput; | private static $rawInput; | ||||
| private static $oldMemoryLimit; | private static $oldMemoryLimit; | ||||
| private static $phases; | private static $phases; | ||||
| private static $limits = array(); | private static $limits = array(); | ||||
| private static $requestPath; | |||||
| /* -( Accessing Request Information )-------------------------------------- */ | /* -( Accessing Request Information )-------------------------------------- */ | ||||
| /** | /** | ||||
| * @task info | * @task info | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | /* -( Startup Hooks )------------------------------------------------------ */ | ||||
| * @task hook | * @task hook | ||||
| */ | */ | ||||
| public static function didStartup($start_time) { | public static function didStartup($start_time) { | ||||
| self::$startTime = $start_time; | self::$startTime = $start_time; | ||||
| self::$phases = array(); | self::$phases = array(); | ||||
| self::$accessLog = null; | self::$accessLog = null; | ||||
| self::$requestPath = null; | |||||
| static $registered; | static $registered; | ||||
| if (!$registered) { | if (!$registered) { | ||||
| // NOTE: This protects us against multiple calls to didStartup() in the | // NOTE: This protects us against multiple calls to didStartup() in the | ||||
| // same request, but also against repeated requests to the same | // same request, but also against repeated requests to the same | ||||
| // interpreter state, which we may implement in the future. | // interpreter state, which we may implement in the future. | ||||
| register_shutdown_function(array(__CLASS__, 'didShutdown')); | register_shutdown_function(array(__CLASS__, 'didShutdown')); | ||||
| $registered = true; | $registered = true; | ||||
| } | } | ||||
| self::setupPHP(); | self::setupPHP(); | ||||
| self::verifyPHP(); | self::verifyPHP(); | ||||
| // If we've made it this far, the environment isn't completely broken so | // If we've made it this far, the environment isn't completely broken so | ||||
| // we can switch over to relying on our own exception recovery mechanisms. | // we can switch over to relying on our own exception recovery mechanisms. | ||||
| ini_set('display_errors', 0); | ini_set('display_errors', 0); | ||||
| self::connectRateLimits(); | self::connectRateLimits(); | ||||
| self::normalizeInput(); | self::normalizeInput(); | ||||
| self::verifyRewriteRules(); | self::readRequestPath(); | ||||
| self::beginOutputCapture(); | self::beginOutputCapture(); | ||||
| } | } | ||||
| /** | /** | ||||
| * @task hook | * @task hook | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 395 Lines • ▼ Show 20 Lines | if (isset($_SERVER['HTTP_PROXY'])) { | ||||
| 'This HTTP request included a "Proxy:" header, poisoning the '. | 'This HTTP request included a "Proxy:" header, poisoning the '. | ||||
| 'environment (CVE-2016-5385 / httpoxy). Declining to process this '. | 'environment (CVE-2016-5385 / httpoxy). Declining to process this '. | ||||
| 'request. For details, see: https://phurl.io/u/httpoxy'); | 'request. For details, see: https://phurl.io/u/httpoxy'); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * @task validation | * @task request-path | ||||
| */ | */ | ||||
| private static function verifyRewriteRules() { | private static function readRequestPath() { | ||||
| // See T13575. The request path may be provided in: | |||||
| // | |||||
| // - the "$_GET" parameter "__path__" (normal for Apache and nginx); or | |||||
| // - the "$_SERVER" parameter "REQUEST_URI" (normal for the PHP builtin | |||||
| // webserver). | |||||
| // | |||||
| // Locate it wherever it is, and store it for later use. Note that writing | |||||
| // to "$_REQUEST" here won't always work, because later code may rebuild | |||||
| // "$_REQUEST" from other sources. | |||||
| if (isset($_REQUEST['__path__']) && strlen($_REQUEST['__path__'])) { | if (isset($_REQUEST['__path__']) && strlen($_REQUEST['__path__'])) { | ||||
| self::setRequestPath($_REQUEST['__path__']); | |||||
| return; | return; | ||||
| } | } | ||||
| if (php_sapi_name() == 'cli-server') { | |||||
| // Compatibility with PHP 5.4+ built-in web server. | // Compatibility with PHP 5.4+ built-in web server. | ||||
| $url = parse_url($_SERVER['REQUEST_URI']); | if (php_sapi_name() == 'cli-server') { | ||||
| $_REQUEST['__path__'] = $url['path']; | $path = parse_url($_SERVER['REQUEST_URI']); | ||||
| self::setRequestPath($path['path']); | |||||
| return; | return; | ||||
| } | } | ||||
| if (!isset($_REQUEST['__path__'])) { | if (!isset($_REQUEST['__path__'])) { | ||||
| self::didFatal( | self::didFatal( | ||||
| "Request parameter '__path__' is not set. Your rewrite rules ". | "Request parameter '__path__' is not set. Your rewrite rules ". | ||||
| "are not configured correctly."); | "are not configured correctly."); | ||||
| } | } | ||||
| if (!strlen($_REQUEST['__path__'])) { | if (!strlen($_REQUEST['__path__'])) { | ||||
| self::didFatal( | self::didFatal( | ||||
| "Request parameter '__path__' is set, but empty. Your rewrite rules ". | "Request parameter '__path__' is set, but empty. Your rewrite rules ". | ||||
| "are not configured correctly. The '__path__' should always ". | "are not configured correctly. The '__path__' should always ". | ||||
| "begin with a '/'."); | "begin with a '/'."); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * @task request-path | |||||
| */ | |||||
| public static function getRequestPath() { | |||||
| $path = self::$requestPath; | |||||
| if ($path === null) { | |||||
| self::didFatal( | |||||
| 'Request attempted to access request path, but no request path is '. | |||||
| 'available for this request. You may be calling web request code '. | |||||
| 'from a non-request context, or your webserver may not be passing '. | |||||
| 'a request path to Phabricator in a format that it understands.'); | |||||
| } | |||||
| return $path; | |||||
| } | |||||
| /** | |||||
| * @task request-path | |||||
| */ | |||||
| public static function setRequestPath($path) { | |||||
| self::$requestPath = $path; | |||||
| } | |||||
| /* -( Rate Limiting )------------------------------------------------------ */ | /* -( Rate Limiting )------------------------------------------------------ */ | ||||
| /** | /** | ||||
| * Add a new client limits. | * Add a new client limits. | ||||
| * | * | ||||
| * @param PhabricatorClientLimit New limit. | * @param PhabricatorClientLimit New limit. | ||||
| ▲ Show 20 Lines • Show All 135 Lines • Show Last 20 Lines | |||||