Permalink
Browse files

Consolidate environmental initialization

Summary:
We have a bunch of code duplication now between __init_script__.php and webroot/index.php. Consoldiate these methods and move them into PhabricatorEnv.

Merge PhabricatorRequestOverseer into PhabricatorStartup.

Test Plan: Loaded page, ran script. Wiped PHABRICATOR_ENV; loaded page, ran script; got errors.

Reviewers: btrahan, vrana

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2223

Differential Revision: https://secure.phabricator.com/D4283
  • Loading branch information...
1 parent ed58f6c commit 9e6d59829ced8756d89def89fe35f2bb8eee38f7 @epriestley epriestley committed Dec 25, 2012
@@ -1,72 +1,24 @@
<?php
-error_reporting(E_ALL | E_STRICT);
-ini_set('display_errors', 1);
-
-$include_path = ini_get('include_path');
-ini_set(
- 'include_path',
- $include_path.PATH_SEPARATOR.dirname(__FILE__).'/../../');
-@include_once 'libphutil/scripts/__init_script__.php';
-if (!@constant('__LIBPHUTIL__')) {
- echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ".
- "include the parent directory of libphutil/.\n";
- exit(1);
-}
-
-phutil_load_library(dirname(__FILE__).'/../src/');
-
-// NOTE: This is dangerous in general, but we know we're in a script context and
-// are not vulnerable to CSRF.
-AphrontWriteGuard::allowDangerousUnguardedWrites(true);
-
-require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php';
-
-$env = isset($_SERVER['PHABRICATOR_ENV'])
- ? $_SERVER['PHABRICATOR_ENV']
- : getenv('PHABRICATOR_ENV');
-if (!$env) {
- echo phutil_console_wrap(
- phutil_console_format(
- "**ERROR**: PHABRICATOR_ENV Not Set\n\n".
- "Define the __PHABRICATOR_ENV__ environment variable before running ".
- "this script. You can do it on the command line like this:\n\n".
- " $ PHABRICATOR_ENV=__custom/myconfig__ %s ...\n\n".
- "Replace __custom/myconfig__ with the path to your configuration file. ".
- "For more information, see the 'Configuration Guide' in the ".
- "Phabricator documentation.\n\n",
- $argv[0]));
- exit(1);
-}
-
-$conf = phabricator_read_config_file($env);
-$conf['phabricator.env'] = $env;
-
-PhabricatorEnv::setEnvConfig($conf);
-
-phutil_load_library('arcanist/src');
-
-foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) {
- phutil_load_library($library);
-}
-
-PhutilErrorHandler::initialize();
-PhabricatorEventEngine::initialize();
-
-$tz = PhabricatorEnv::getEnvConfig('phabricator.timezone');
-if ($tz) {
- date_default_timezone_set($tz);
+function init_phabricator_script() {
+ error_reporting(E_ALL | E_STRICT);
+ ini_set('display_errors', 1);
+
+ $include_path = ini_get('include_path');
+ ini_set(
+ 'include_path',
+ $include_path.PATH_SEPARATOR.dirname(__FILE__).'/../../');
+ @include_once 'libphutil/scripts/__init_script__.php';
+ if (!@constant('__LIBPHUTIL__')) {
+ echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ".
+ "include the parent directory of libphutil/.\n";
+ exit(1);
+ }
+
+ phutil_load_library('arcanist/src');
+ phutil_load_library(dirname(__FILE__).'/../src/');
+
+ PhabricatorEnv::initializeScriptEnvironment();
}
-$translation = PhabricatorEnv::newObjectFromConfig('translation.provider');
-PhutilTranslator::getInstance()
- ->setLanguage($translation->getLanguage())
- ->addTranslations($translation->getTranslations());
-
-// Append any paths to $PATH if we need to.
-$paths = PhabricatorEnv::getEnvConfig('environment.append-paths');
-if (!empty($paths)) {
- $current_env_path = getenv('PATH');
- $new_env_paths = implode(PATH_SEPARATOR, $paths);
- putenv('PATH='.$current_env_path.PATH_SEPARATOR.$new_env_paths);
-}
+init_phabricator_script();
@@ -1080,7 +1080,6 @@
'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php',
'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php',
'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php',
- 'PhabricatorRequestOverseer' => 'infrastructure/PhabricatorRequestOverseer.php',
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php',
'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php',
@@ -53,6 +53,102 @@
private static $env;
private static $stack = array();
+ /**
+ * @phutil-external-symbol class PhabricatorStartup
+ */
+ public static function initializeWebEnvironment() {
+ $env = self::getSelectedEnvironmentName();
+ if (!$env) {
+ PhabricatorStartup::didFatal(
+ "The 'PHABRICATOR_ENV' environmental variable is not defined. Modify ".
+ "your httpd.conf to include 'SetEnv PHABRICATOR_ENV <env>', where ".
+ "'<env>' is one of 'development', 'production', or a custom ".
+ "environment.");
+ }
+
+ self::initializeCommonEnvironment();
+ }
+
+ public static function initializeScriptEnvironment() {
+ $env = self::getSelectedEnvironmentName();
+ if (!$env) {
+ echo phutil_console_wrap(
+ phutil_console_format(
+ "**ERROR**: PHABRICATOR_ENV Not Set\n\n".
+ "Define the __PHABRICATOR_ENV__ environment variable before ".
+ "running this script. You can do it on the command line like ".
+ "this:\n\n".
+ " $ PHABRICATOR_ENV=__custom/myconfig__ %s ...\n\n".
+ "Replace __custom/myconfig__ with the path to your configuration ".
+ "file. For more information, see the 'Configuration Guide' in the ".
+ "Phabricator documentation.\n\n",
+ $GLOBALS['argv'][0]));
+ exit(1);
+ }
+
+ self::initializeCommonEnvironment();
+
+ // NOTE: This is dangerous in general, but we know we're in a script context
+ // and are not vulnerable to CSRF.
+ AphrontWriteGuard::allowDangerousUnguardedWrites(true);
+ }
+
+ /**
+ * @phutil-external-symbol function phabricator_read_config_file
+ */
+ private static function initializeCommonEnvironment() {
+ $env = self::getSelectedEnvironmentName();
+
+ $root = dirname(phutil_get_library_root('phabricator'));
+ require_once $root.'/conf/__init_conf__.php';
+ $conf = phabricator_read_config_file($env);
+ $conf['phabricator.env'] = $env;
+
+ PhabricatorEnv::setEnvConfig($conf);
+
+ PhutilErrorHandler::initialize();
+
+ $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone');
+ if ($tz) {
+ date_default_timezone_set($tz);
+ }
+
+ // Append any paths to $PATH if we need to.
+ $paths = PhabricatorEnv::getEnvConfig('environment.append-paths');
+ if (!empty($paths)) {
+ $current_env_path = getenv('PATH');
+ $new_env_paths = implode(PATH_SEPARATOR, $paths);
+ putenv('PATH='.$current_env_path.PATH_SEPARATOR.$new_env_paths);
+ }
+
+ foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) {
+ phutil_load_library($library);
+ }
+
+ PhabricatorEventEngine::initialize();
+
+ $translation = PhabricatorEnv::newObjectFromConfig('translation.provider');
+ PhutilTranslator::getInstance()
+ ->setLanguage($translation->getLanguage())
+ ->addTranslations($translation->getTranslations());
+ }
+
+ public static function getSelectedEnvironmentName() {
+ $env_var = 'PHABRICATOR_ENV';
+
+ $env = idx($_SERVER, $env_var);
+
+ if (!$env) {
+ $env = getenv($env_var);
+ }
+
+ if (!$env) {
+ $env = idx($_ENV, $env_var);
+ }
+
+ return $env;
+ }
+
/* -( Reading Configuration )---------------------------------------------- */
@@ -1,98 +0,0 @@
-<?php
-
-final class PhabricatorRequestOverseer {
-
- public function didStartup() {
- $this->detectPostMaxSizeTriggered();
- }
-
- /**
- * Detect if this request has had its POST data stripped by exceeding the
- * 'post_max_size' PHP configuration limit.
- *
- * PHP has a setting called 'post_max_size'. If a POST request arrives with
- * a body larger than the limit, PHP doesn't generate $_POST but processes
- * the request anyway, and provides no formal way to detect that this
- * happened.
- *
- * We can still read the entire body out of `php://input`. However according
- * to the documentation the stream isn't available for "multipart/form-data"
- * (on nginx + php-fpm it appears that it is available, though, at least) so
- * any attempt to generate $_POST would be fragile.
- *
- * @phutil-external-symbol class PhabricatorStartup
- */
- private function detectPostMaxSizeTriggered() {
- // If this wasn't a POST, we're fine.
- if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- return;
- }
-
- // If there's POST data, clearly we're in good shape.
- if ($_POST) {
- return;
- }
-
- // For HTML5 drag-and-drop file uploads, Safari submits the data as
- // "application/x-www-form-urlencoded". For most files this generates
- // something in POST because most files decode to some nonempty (albeit
- // meaningless) value. However, some files (particularly small images)
- // don't decode to anything. If we know this is a drag-and-drop upload,
- // we can skip this check.
- if (isset($_REQUEST['__upload__'])) {
- return;
- }
-
- // PHP generates $_POST only for two content types. This routing happens
- // in `main/php_content_types.c` in PHP. Normally, all forms use one of
- // these content types, but some requests may not -- for example, Firefox
- // submits files sent over HTML5 XMLHTTPRequest APIs with the Content-Type
- // of the file itself. If we don't have a recognized content type, we
- // don't need $_POST.
- //
- // NOTE: We use strncmp() because the actual content type may be something
- // like "multipart/form-data; boundary=...".
- //
- // NOTE: Chrome sometimes omits this header, see some discussion in T1762
- // and http://code.google.com/p/chromium/issues/detail?id=6800
- $content_type = idx($_SERVER, 'CONTENT_TYPE', '');
-
- $parsed_types = array(
- 'application/x-www-form-urlencoded',
- 'multipart/form-data',
- );
-
- $is_parsed_type = false;
- foreach ($parsed_types as $parsed_type) {
- if (strncmp($content_type, $parsed_type, strlen($parsed_type)) === 0) {
- $is_parsed_type = true;
- break;
- }
- }
-
- if (!$is_parsed_type) {
- return;
- }
-
- // Check for 'Content-Length'. If there's no data, we don't expect $_POST
- // to exist.
- $length = (int)$_SERVER['CONTENT_LENGTH'];
- if (!$length) {
- return;
- }
-
- // Time to fatal: we know this was a POST with data that should have been
- // populated into $_POST, but it wasn't.
-
- $config = ini_get('post_max_size');
- PhabricatorStartup::didFatal(
- "As received by the server, this request had a nonzero content length ".
- "but no POST data.\n\n".
- "Normally, this indicates that it exceeds the 'post_max_size' setting ".
- "in the PHP configuration on the server. Increase the 'post_max_size' ".
- "setting or reduce the size of the request.\n\n".
- "Request size according to 'Content-Length' was '{$length}', ".
- "'post_max_size' is set to '{$config}'.");
- }
-
-}
Oops, something went wrong.

0 comments on commit 9e6d598

Please sign in to comment.