Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/patches/128.phabricatorcom.sql b/resources/sql/patches/128.phabricatorcom.sql
new file mode 100644
index 0000000000..02acb07c0a
--- /dev/null
+++ b/resources/sql/patches/128.phabricatorcom.sql
@@ -0,0 +1,3 @@
+UPDATE phabricator_directory.directory_item SET
+ href = REPLACE(href, 'http://phabricator.com/', 'http://www.phabricator.com/')
+ WHERE href LIKE 'http://phabricator.com/%';
diff --git a/scripts/install/install_rhel-derivs.sh b/scripts/install/install_rhel-derivs.sh
index 712f7a0a27..f6b6c05322 100755
--- a/scripts/install/install_rhel-derivs.sh
+++ b/scripts/install/install_rhel-derivs.sh
@@ -1,142 +1,142 @@
#!/bin/bash
confirm() {
echo "Press RETURN to continue, or ^C to cancel.";
read -e ignored
}
RHEL_VER_FILE="/etc/redhat-release"
if [[ ! -f $RHEL_VER_FILE ]]
then
echo "It looks like you're not running a Red Hat-derived distribution."
echo "This script is intended to install Phabricator on RHEL-derived"
echo "distributions such as RHEL, Fedora, CentOS, and Scientific Linux."
echo "Proceed with caution."
confirm
fi
echo "PHABRICATOR RED HAT DERIVATIVE INSTALLATION SCRIPT";
echo "This script will install Phabricator and all of its core dependencies.";
echo "Run it from the directory you want to install into.";
echo
RHEL_REGEX="release ([0-9]+)\."
if [[ $(cat $RHEL_VER_FILE) =~ $RHEL_REGEX ]]
then
RHEL_MAJOR_VER=${BASH_REMATCH[1]}
else
echo "Ut oh, we were unable to determine your distribution's major"
echo "version number. Please make sure you're running 6.0+ before"
echo "proceeding."
confirm
fi
if [[ $RHEL_MAJOR_VER < 6 ]]
then
echo "** WARNING **"
echo "A major version less than 6 was detected. Because of this,"
echo "several needed dependencies are not available via default repos."
echo "Specifically, RHEL 5 does not have a PEAR package for php53-*."
echo "We will attempt to install it manually, for APC. Please be careful."
confirm
fi
echo "Phabricator will be installed to: $(pwd).";
confirm
echo "Testing sudo/root..."
if [[ $EUID -ne 0 ]] # Check if we're root. If we are, continue.
then
sudo true
SUDO="sudo"
if [[ $? -ne 0 ]]
then
echo "ERROR: You must be able to sudo to run this script, or run it as root.";
exit 1
fi
fi
if [[ $RHEL_MAJOR_VER == 5 ]]
then
# RHEL 5's "php" package is actually 5.1. The "php53" package won't let us install php-pecl-apc.
# (it tries to pull in php 5.1 stuff) ...
echo "Adding EPEL repo, for git."
$SUDO rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
YUMCOMMAND="$SUDO yum install httpd git php53 php53-cli php53-mysql php53-process php53-devel php53-gd gcc wget make pcre-devel mysql-server"
else
# RHEL 6+ defaults with php 5.3
YUMCOMMAND="$SUDO yum install httpd git php php-cli php-mysql php-process php-devel php-gd php-pecl-apc php-pecl-json mysql-server"
fi
echo "Dropping to yum to install dependencies..."
echo "Running: ${YUMCOMMAND}"
echo "Yum will prompt you with [Y/n] to continue installing."
$YUMCOMMAND
if [[ $? -ne 0 ]]
then
echo "The yum command failed. Please fix the errors and re-run this script."
exit 1
fi
if [[ $RHEL_MAJOR_VER == 5 ]]
then
# Now that we've ensured all the devel packages required for pecl/apc are there, let's
# set up PEAR, and install apc.
echo "Attempting to install PEAR"
wget http://pear.php.net/go-pear.phar
echo "Downloading PEAR: $PEARCOMMAND"
$SUDO php go-pear.phar && $SUDO pecl install apc
fi
if [[ $? -ne 0 ]]
then
echo "The apc install failed. Continuing without APC, performance may be impacted."
fi
if [[ "$(pidof httpd)" ]]
then
echo "If php was installed above, please run: /etc/init.d/httpd graceful"
else
echo "Please remember to start the httpd with: /etc/init.d/httpd start"
fi
if [[ ! "$(pidof mysql)" ]]
then
echo "Please remember to start the mysql server: /etc/init.d/mysqld start"
fi
confirm
if [[ ! -e libphutil ]]
then
git clone git://github.com/facebook/libphutil.git
else
(cd libphutil && git pull --rebase)
fi
if [[ ! -e arcanist ]]
then
git clone git://github.com/facebook/arcanist.git
else
(cd arcanist && git pull --rebase)
fi
if [[ ! -e phabricator ]]
then
git clone git://github.com/facebook/phabricator.git
else
(cd phabricator && git pull --rebase)
fi
(cd phabricator && git submodule update --init)
echo
echo
echo "Install probably worked mostly correctly. Continue with the 'Configuration Guide':";
echo
-echo " http://phabricator.com/docs/phabricator/article/Configuration_Guide.html";
\ No newline at end of file
+echo " http://www.phabricator.com/docs/phabricator/article/Configuration_Guide.html";
\ No newline at end of file
diff --git a/scripts/install/install_ubuntu.sh b/scripts/install/install_ubuntu.sh
index bd6d0452e6..1b5c04a0ae 100755
--- a/scripts/install/install_ubuntu.sh
+++ b/scripts/install/install_ubuntu.sh
@@ -1,89 +1,89 @@
#!/bin/bash
confirm() {
echo "Press RETURN to continue, or ^C to cancel.";
read -e ignored
}
GIT='git'
LTS="Ubuntu 10.04"
ISSUE=`cat /etc/issue`
if [[ $ISSUE != Ubuntu* ]]
then
echo "This script is intended for use on Ubuntu, but this system appears";
echo "to be something else. Your results may vary.";
echo
confirm
elif [[ `expr match "$ISSUE" "$LTS"` -eq ${#LTS} ]]
then
GIT='git-core'
fi
echo "PHABRICATOR UBUNTU INSTALL SCRIPT";
echo "This script will install Phabricator and all of its core dependencies.";
echo "Run it from the directory you want to install into.";
echo
ROOT=`pwd`
echo "Phabricator will be installed to: ${ROOT}.";
confirm
echo "Testing sudo..."
sudo true
if [ $? -ne 0 ]
then
echo "ERROR: You must be able to sudo to run this script.";
exit 1;
fi;
echo "Installing dependencies: git, apache, mysql, php...";
echo
set +x
sudo apt-get -qq update
sudo apt-get install $GIT mysql-server apache2 php5 php5-mysql php5-gd php5-dev php5-curl php-apc php5-cli dpkg-dev
HAVEPCNTL=`php -r "echo extension_loaded('pcntl');"`
if [ $HAVEPCNTL != "1" ]
then
echo "Installing pcntl...";
echo
apt-get source php5
PHP5=`ls -1F | grep '^php5-.*/$'`
(cd $PHP5/ext/pcntl && phpize && ./configure && make && sudo make install)
else
echo "pcntl already installed";
fi
if [ ! -e libphutil ]
then
git clone git://github.com/facebook/libphutil.git
else
(cd libphutil && git pull --rebase)
fi
if [ ! -e arcanist ]
then
git clone git://github.com/facebook/arcanist.git
else
(cd arcanist && git pull --rebase)
fi
if [ ! -e phabricator ]
then
git clone git://github.com/facebook/phabricator.git
else
(cd phabricator && git pull --rebase)
fi
(cd phabricator && git submodule update --init)
echo
echo
echo "Install probably worked mostly correctly. Continue with the 'Configuration Guide':";
echo
-echo " http://phabricator.com/docs/phabricator/article/Configuration_Guide.html";
+echo " http://www.phabricator.com/docs/phabricator/article/Configuration_Guide.html";
echo
echo "You can delete any php5-* stuff that's left over in this directory if you want.";
diff --git a/src/docs/installation_guide.diviner b/src/docs/installation_guide.diviner
index 563af05654..ad5a178228 100644
--- a/src/docs/installation_guide.diviner
+++ b/src/docs/installation_guide.diviner
@@ -1,130 +1,130 @@
@title Installation Guide
@group intro
This document contains basic install instructions to get Phabricator up and
running.
= Installation Requirements =
Phabricator is a LAMP application suite, so you basically need LAMP:
- **Linux**: Some flavor of Linux is required. Mac OS X is an acceptable
flavor of Linux. Windows is not an acceptable flavor of Linux. Phabricator
will not install or work properly on Windows. (If you want it to, send
patches.) Phabricator has active contributors running it on Mac OS X, Amazon
Linux, Ubuntu, RHEL and CentOS; if you run into issues on other flavors,
send patches or complaints.
- **Apache** (or nginx): You need Apache (or nginx). You might be able to use
something else, but you're on your own.
- **MySQL**: You need MySQL.
- **PHP**: You need PHP 5.2 or newer.
NOTE: The command line interface to Phabricator, "Arcanist", //does// work on
Windows. For instructions, see @{article:Arcanist User Guide: Windows}.
You'll probably also need a **domain name** and you'll certainly need
**a computer** with a connection to **the internet**.
= Installing Required Components =
If you are installing on Ubuntu or an RedHat derivative, there are install
scripts available which should handle most of the things discussed in this
document for you:
- - **RedHat Derivatives**: <http://phabricator.com/rsrc/install/install_rhel-derivs.sh>
- - **Ubuntu**: <http://phabricator.com/rsrc/install/install_ubuntu.sh>
+ - **RedHat Derivatives**: <http://www.phabricator.com/rsrc/install/install_rhel-derivs.sh>
+ - **Ubuntu**: <http://www.phabricator.com/rsrc/install/install_ubuntu.sh>
If those work for you, you can skip directly to the
@{article:Configuration Guide}. These scripts are also available in the
##scripts/install## directory in the project itself.
Otherwise, here's a general description of what you need to install:
- git (usually called "git" in package management systems)
- Apache (usually "httpd" or "apache2") (or nginx)
- MySQL Server (usually "mysqld" or "mysql-server")
- PHP (usually "php")
- Required PHP extensions: mbstring, iconv, mysql, curl, pcntl (these might be
something like "php-mysql" or "php5-mysql")
- Optional PHP extensions: gd, apc (special instructions for APC are available
below if you have difficulty installing it), xhprof (instructions below,
you only need this if you are developing Phabricator)
If you already have LAMP setup, you've probably already got everything you need.
It may also be helpful to refer to the install scripts above, even if they don't
work for your system.
Now that you have all that stuff installed, grab Phabricator and its
dependencies:
$ cd somewhere/ # pick some install directory
somewhere/ $ git clone git://github.com/facebook/libphutil.git
somewhere/ $ git clone git://github.com/facebook/arcanist.git
somewhere/ $ git clone git://github.com/facebook/phabricator.git
somewhere/ $ cd phabricator
somewhere/phabricator/ $ git submodule update --init
= Installing APC (Optional) =
Like everything else written in PHP, Phabricator will run much faster with APC
installed. You likely need to install "pcre-devel" first:
sudo yum install pcre-devel
Then you have two options. Either install via PECL (try this first):
sudo yum install php-pear
sudo pecl install apc
**If that doesn't work**, grab the package from PECL directly and follow the
build instructions there:
http://pecl.php.net/package/APC
Installing APC is optional but **strongly recommended**, especially on
production hosts.
Once APC is installed, test that it is available by running:
php -i | grep apc
If it doesn't show up, add:
extension=apc.so
..to "/etc/php.d/apc.ini" or the "php.ini" file indicated by "php -i".
= Installing XHProf (Optional) =
XHProf is a PHP profiling tool. You don't need to install it unless you are
developing Phabricator and making performance changes.
You can install xhprof with:
$ pecl install xhprof
If you have a PEAR version prior to 1.9.3, you may run into a `phpize` failure.
If so, you can download the source and build it with:
$ cd extension/
$ phpize
$ ./configure
$ make
$ sudo make install
You may also need to add "##extension=xhprof.so#" to your php.ini.
See <https://bugs.php.net/bug.php?id=59747> for more information.
= Updating Phabricator =
Since Phabricator is under active development, you should update frequently.
You can use a script similar to this one to automate the process:
- http://phabricator.com/rsrc/install/update_phabricator.sh
+ http://www.phabricator.com/rsrc/install/update_phabricator.sh
= Next Steps =
Continue by:
- configuring Phabricator with the @{article:Configuration Guide}.
diff --git a/src/infrastructure/env/PhabricatorEnv.php b/src/infrastructure/env/PhabricatorEnv.php
index 76e99fa09f..cda86bb545 100644
--- a/src/infrastructure/env/PhabricatorEnv.php
+++ b/src/infrastructure/env/PhabricatorEnv.php
@@ -1,184 +1,184 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @task uri URI Validation
*/
final class PhabricatorEnv {
private static $env;
public static function setEnvConfig(array $config) {
self::$env = $config;
}
public static function getEnvConfig($key, $default = null) {
return idx(self::$env, $key, $default);
}
public static function newObjectFromConfig($key, $args = array()) {
$class = self::getEnvConfig($key);
$object = newv($class, $args);
$instanceof = idx(self::getRequiredClasses(), $key);
if (!($object instanceof $instanceof)) {
throw new Exception("Config setting '$key' must be an instance of ".
"'$instanceof', is '".get_class($object)."'.");
}
return $object;
}
public static function getRequiredClasses() {
return array(
'metamta.mail-adapter' => 'PhabricatorMailImplementationAdapter',
'metamta.maniphest.reply-handler' => 'PhabricatorMailReplyHandler',
'metamta.differential.reply-handler' => 'PhabricatorMailReplyHandler',
'metamta.diffusion.reply-handler' => 'PhabricatorMailReplyHandler',
'storage.engine-selector' => 'PhabricatorFileStorageEngineSelector',
'search.engine-selector' => 'PhabricatorSearchEngineSelector',
'differential.field-selector' => 'DifferentialFieldSelector',
'maniphest.custom-task-extensions-class' => 'ManiphestTaskExtensions',
'aphront.default-application-configuration-class' =>
'AphrontApplicationConfiguration',
'controller.oauth-registration' =>
'PhabricatorOAuthRegistrationController',
'mysql.implementation' => 'AphrontMySQLDatabaseConnectionBase',
'differential.attach-task-class' => 'DifferentialTasksAttacher',
'mysql.configuration-provider' => 'DatabaseConfigurationProvider',
);
}
public static function envConfigExists($key) {
return array_key_exists($key, self::$env);
}
public static function getURI($path) {
return rtrim(self::getEnvConfig('phabricator.base-uri'), '/').$path;
}
public static function getProductionURI($path) {
// If we're passed a URI which already has a domain, simply return it
// unmodified. In particular, files may have URIs which point to a CDN
// domain.
$uri = new PhutilURI($path);
if ($uri->getDomain()) {
return $path;
}
$production_domain = self::getEnvConfig('phabricator.production-uri');
if (!$production_domain) {
$production_domain = self::getEnvConfig('phabricator.base-uri');
}
return rtrim($production_domain, '/').$path;
}
public static function getCDNURI($path) {
$alt = self::getEnvConfig('security.alternate-file-domain');
if (!$alt) {
$alt = self::getEnvConfig('phabricator.base-uri');
}
$uri = new PhutilURI($alt);
$uri->setPath($path);
return (string)$uri;
}
public static function getAllConfigKeys() {
return self::$env;
}
public static function getDoclink($resource) {
- return 'http://phabricator.com/docs/phabricator/'.$resource;
+ return 'http://www.phabricator.com/docs/phabricator/'.$resource;
}
/* -( URI Validation )----------------------------------------------------- */
/**
* Detect if a URI satisfies either @{method:isValidLocalWebResource} or
* @{method:isValidRemoteWebResource}, i.e. is a page on this server or the
* URI of some other resource which has a valid protocol. This rejects
* garbage URIs and URIs with protocols which do not appear in the
* ##uri.allowed-protocols## configuration, notably 'javascript:' URIs.
*
* NOTE: This method is generally intended to reject URIs which it may be
* unsafe to put in an "href" link attribute.
*
* @param string URI to test.
* @return bool True if the URI identifies a web resource.
* @task uri
*/
public static function isValidWebResource($uri) {
return self::isValidLocalWebResource($uri) ||
self::isValidRemoteWebResource($uri);
}
/**
* Detect if a URI identifies some page on this server.
*
* NOTE: This method is generally intended to reject URIs which it may be
* unsafe to issue a "Location:" redirect to.
*
* @param string URI to test.
* @return bool True if the URI identifies a local page.
* @task uri
*/
public static function isValidLocalWebResource($uri) {
$uri = (string)$uri;
if (!strlen($uri)) {
return false;
}
if (preg_match('/\s/', $uri)) {
// PHP hasn't been vulnerable to header injection attacks for a bunch of
// years, but we can safely reject these anyway since they're never valid.
return false;
}
// Valid URIs must begin with '/', followed by the end of the string or some
// other non-'/' character. This rejects protocol-relative URIs like
// "//evil.com/evil_stuff/".
return (bool)preg_match('@^/([^/]|$)@', $uri);
}
/**
* Detect if a URI identifies some valid remote resource.
*
* @param string URI to test.
* @return bool True if a URI idenfies a remote resource with an allowed
* protocol.
* @task uri
*/
public static function isValidRemoteWebResource($uri) {
$uri = (string)$uri;
$proto = id(new PhutilURI($uri))->getProtocol();
if (!$proto) {
return false;
}
$allowed = self::getEnvConfig('uri.allowed-protocols');
if (empty($allowed[$proto])) {
return false;
}
return true;
}
}
diff --git a/src/infrastructure/setup/PhabricatorSetup.php b/src/infrastructure/setup/PhabricatorSetup.php
index fd922a470b..e4573e045d 100644
--- a/src/infrastructure/setup/PhabricatorSetup.php
+++ b/src/infrastructure/setup/PhabricatorSetup.php
@@ -1,835 +1,835 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorSetup {
public static function runSetup() {
header("Content-Type: text/plain");
self::write("PHABRICATOR SETUP\n\n");
// Force browser to stop buffering.
self::write(str_repeat(' ', 2048));
usleep(250000);
self::write("This setup mode will guide you through setting up your ".
"Phabricator configuration.\n");
self::writeHeader("CORE CONFIGURATION");
// NOTE: Test this first since other tests depend on the ability to
// execute system commands and will fail if safe_mode is enabled.
$safe_mode = ini_get('safe_mode');
if ($safe_mode) {
self::writeFailure();
self::write(
"Setup failure! You have 'safe_mode' enabled. Phabricator will not ".
"run in safe mode, and it has been deprecated in PHP 5.3 and removed ".
"in PHP 5.4.\n");
return;
} else {
self::write(" okay PHP's deprecated 'safe_mode' is disabled.\n");
}
// NOTE: Also test this early since we can't include files from other
// libraries if this is set strictly.
$open_basedir = ini_get('open_basedir');
if ($open_basedir) {
// 'open_basedir' restricts which files we're allowed to access with
// file operations. This might be okay -- we don't need to write to
// arbitrary places in the filesystem -- but we need to access certain
// resources. This setting is unlikely to be providing any real measure
// of security so warn even if things look OK.
try {
phutil_require_module('phutil', 'utils');
$open_libphutil = true;
} catch (Exception $ex) {
$message = $ex->getMessage();
self::write("Unable to load modules from libphutil: {$message}\n");
$open_libphutil = false;
}
try {
phutil_require_module('arcanist', 'workflow/base');
$open_arcanist = true;
} catch (Exception $ex) {
$message = $ex->getMessage();
self::write("Unable to load modules from Arcanist: {$message}\n");
$open_arcanist = false;
}
$open_urandom = false;
try {
Filesystem::readRandomBytes(1);
$open_urandom = true;
} catch (FilesystemException $ex) {
self::write($ex->getMessage()."\n");
}
try {
$tmp = new TempFile();
file_put_contents($tmp, '.');
$open_tmp = @fopen((string)$tmp, 'r');
} catch (Exception $ex) {
$message = $ex->getMessage();
$dir = sys_get_temp_dir();
self::write("Unable to open temp files from '{$dir}': {$message}\n");
$open_tmp = false;
}
if (!$open_urandom || !$open_tmp || !$open_libphutil || !$open_arcanist) {
self::writeFailure();
self::write(
"Setup failure! Your server is configured with 'open_basedir' in ".
"php.ini which prevents Phabricator from opening files it needs to ".
"access. Either make the setting more permissive or remove it. It ".
"is unlikely you derive significant security benefits from having ".
"this configured; files outside this directory can still be ".
"accessed through system command execution.");
return;
} else {
self::write(
"[WARN] You have an 'open_basedir' configured in your php.ini. ".
"Although the setting seems permissive enough that Phabricator ".
"will run properly, you may run into problems because of it. It is ".
"unlikely you gain much real security benefit from having it ".
"configured, because the application can still access files outside ".
"the 'open_basedir' by running system commands.\n");
}
} else {
self::write(" okay 'open_basedir' is not set.\n");
}
if (!PhabricatorEnv::getEnvConfig('security.alternate-file-domain')) {
self::write(
"[WARN] You have not configured 'security.alternate-file-domain'. ".
"This makes your installation vulnerable to attack. Make sure you ".
"read the documentation for this parameter and understand the ".
"consequences of leaving it unconfigured.\n");
}
$path = getenv('PATH');
if (empty($path)) {
self::writeFailure();
self::write(
"Setup failure! The environmental \$PATH variable is empty. ".
"Phabricator needs to execute system commands like 'svn', 'git', ".
"'hg', and 'diff'. Set up your webserver so that it passes a valid ".
"\$PATH to the PHP process.\n\n");
if (php_sapi_name() == 'fpm-fcgi') {
self::write(
"You're running php-fpm, so the easiest way to do this is to add ".
"this line to your php-fpm.conf:\n\n".
" env[PATH] = /usr/local/bin:/usr/bin:/bin\n\n".
"Then restart php-fpm.\n");
}
return;
} else {
self::write(" okay \$PATH is nonempty.\n");
}
self::write("[OKAY] Core configuration OKAY.\n");
self::writeHeader("REQUIRED PHP EXTENSIONS");
$extensions = array(
'mysql',
'hash',
'json',
'openssl',
'mbstring',
'iconv',
// There is a chance we might not need this, but some configurations (like
// Amazon SES) will require it. Just mark it 'required' since it's widely
// available and relatively core.
'curl',
);
foreach ($extensions as $extension) {
$ok = self::requireExtension($extension);
if (!$ok) {
self::writeFailure();
self::write("Setup failure! Install PHP extension '{$extension}'.");
return;
}
}
list($err, $stdout, $stderr) = exec_manual('which php');
if ($err) {
self::writeFailure();
self::write("Unable to locate 'php' on the command line from the web ".
"server. Verify that 'php' is in the webserver's PATH.\n".
" err: {$err}\n".
"stdout: {$stdout}\n".
"stderr: {$stderr}\n");
return;
} else {
self::write(" okay PHP binary found on the command line.\n");
$php_bin = trim($stdout);
}
// NOTE: In cPanel + suphp installs, 'php' may be the PHP CGI SAPI, not the
// PHP CLI SAPI. proc_open() will pass the environment to the child process,
// which will re-execute the webpage (causing an infinite number of
// processes to spawn). To test that the 'php' binary is safe to execute,
// we call php_sapi_name() using "env -i" to wipe the environment so it
// doesn't execute another reuqest if it's the wrong binary. We can't use
// "-r" because php-cgi doesn't support that flag.
$tmp_file = new TempFile('sapi.php');
Filesystem::writeFile($tmp_file, '<?php echo php_sapi_name();');
list($err, $stdout, $stderr) = exec_manual(
'/usr/bin/env -i %s -f %s',
$php_bin,
$tmp_file);
if ($err) {
self::writeFailure();
self::write("Unable to execute 'php' on the command line from the web ".
"server.\n".
" err: {$err}\n".
"stdout: {$stdout}\n".
"stderr: {$stderr}\n");
return;
} else {
self::write(" okay PHP is available from the command line.\n");
$sapi = trim($stdout);
if ($sapi != 'cli') {
self::writeFailure();
self::write(
"The 'php' binary on this system uses the '{$sapi}' SAPI, but the ".
"'cli' SAPI is expected. Replace 'php' with the php-cli SAPI ".
"binary, or edit your webserver configuration so the first 'php' ".
"in PATH is the 'cli' SAPI.\n\n".
"If you're running cPanel with suphp, the easiest way to fix this ".
"is to add '/usr/local/bin' before '/usr/bin' for 'env_path' in ".
"suconf.php:\n\n".
' env_path="/bin:/usr/local/bin:/usr/bin"'.
"\n\n");
return;
} else {
self::write(" okay 'php' is CLI SAPI.\n");
}
}
$root = dirname(phutil_get_library_root('phabricator'));
// On RHEL6, doing a distro install of pcntl makes it available from the
// CLI binary but not from the Apache module. This isn't entirely
// unreasonable and we don't need it from Apache, so do an explicit test
// for CLI availability.
list($err, $stdout, $stderr) = exec_manual(
'php %s',
"{$root}/scripts/setup/pcntl_available.php");
if ($err) {
self::writeFailure();
self::write("Unable to execute scripts/setup/pcntl_available.php to ".
"test for the availability of pcntl from the CLI.\n".
" err: {$err}\n".
"stdout: {$stdout}\n".
"stderr: {$stderr}\n");
return;
} else {
if (trim($stdout) == 'YES') {
self::write(" okay pcntl is available from the command line.\n");
self::write("[OKAY] All extensions OKAY\n");
} else {
self::write(" warn pcntl is not available!\n");
self::write("[WARN] *** WARNING *** pcntl extension not available. ".
"You will not be able to run daemons.\n");
}
}
self::writeHeader("GIT SUBMODULES");
if (!Filesystem::pathExists($root.'/.git')) {
self::write(" skip Not a git clone.\n\n");
} else {
list($info) = execx(
'(cd %s && git submodule status)',
$root);
foreach (explode("\n", rtrim($info)) as $line) {
$matches = null;
if (!preg_match('/^(.)([0-9a-f]{40}) (\S+)(?: |$)/', $line, $matches)) {
self::writeFailure();
self::write(
"Setup failure! 'git submodule' produced unexpected output:\n".
$line);
return;
}
$status = $matches[1];
$module = $matches[3];
switch ($status) {
case '-':
case '+':
case 'U':
self::writeFailure();
self::write(
"Setup failure! Git submodule '{$module}' is not up to date. ".
"Run:\n\n".
" cd {$root} && git submodule update --init\n\n".
"...to update submodules.");
return;
case ' ':
self::write(" okay Git submodule '{$module}' up to date.\n");
break;
default:
self::writeFailure();
self::write(
"Setup failure! 'git submodule' reported unknown status ".
"'{$status}' for submodule '{$module}'. This is a bug; report ".
"it to the Phabricator maintainers.");
return;
}
}
}
self::write("[OKAY] All submodules OKAY.\n");
self::writeHeader("BASIC CONFIGURATION");
$env = PhabricatorEnv::getEnvConfig('phabricator.env');
if ($env == 'production' || $env == 'default' || $env == 'development') {
self::writeFailure();
self::write(
"Setup failure! Your PHABRICATOR_ENV is set to '{$env}', which is ".
"a Phabricator environmental default. You should create a custom ".
"environmental configuration instead of editing the defaults ".
"directly. See this document for instructions:\n");
self::writeDoc('article/Configuration_Guide.html');
return;
} else {
$host = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
$host_uri = new PhutilURI($host);
$protocol = $host_uri->getProtocol();
$allowed_protocols = array(
'http' => true,
'https' => true,
);
if (empty($allowed_protocols[$protocol])) {
self::writeFailure();
self::write(
"You must specify the protocol over which your host works (e.g.: ".
"\"http:// or https://\")\nin your custom config file.\nRefer to ".
"'default.conf.php' for documentation on configuration options.\n");
return;
}
if (preg_match('/.*\/$/', $host)) {
self::write(" okay phabricator.base-uri protocol\n");
} else {
self::writeFailure();
self::write(
"You must add a trailing slash at the end of the host\n(e.g.: ".
"\"http://phabricator.example.com/ instead of ".
"http://phabricator.example.com\")\nin your custom config file.".
"\nRefer to 'default.conf.php' for documentation on configuration ".
"options.\n");
return;
}
$host_domain = $host_uri->getDomain();
if (strpos($host_domain, '.') !== false) {
self::write(" okay phabricator.base-uri domain\n");
} else {
self::writeFailure();
self::write(
"You must host Phabricator on a domain that contains a dot ('.'). ".
"The current domain, '{$host_domain}', does not have a dot, so some ".
"browsers will not set cookies on it. For instance, ".
"'http://example.com/ is OK, but 'http://example/' won't work. ".
"If you are using localhost, create an entry in the hosts file like ".
"'127.0.0.1 example.com', and access the localhost with ".
"'http://example.com/'.");
return;
}
}
$timezone = nonempty(
PhabricatorEnv::getEnvConfig('phabricator.timezone'),
ini_get('date.timezone'));
if (!$timezone) {
self::writeFailure();
self::write(
"Setup failure! Your configuration fails to specify a server ".
"timezone. Either set 'date.timezone' in your php.ini or ".
"'phabricator.timezone' in your Phabricator configuration. See the ".
"PHP documentation for a list of supported timezones:\n\n".
"http://us.php.net/manual/en/timezones.php\n");
return;
} else {
self::write(" okay Timezone '{$timezone}' configured.\n");
}
self::write("[OKAY] Basic configuration OKAY\n");
$issue_gd_warning = false;
self::writeHeader('GD LIBRARY');
if (extension_loaded('gd')) {
self::write(" okay Extension 'gd' is loaded.\n");
$image_type_map = array(
'imagepng' => 'PNG',
'imagegif' => 'GIF',
'imagejpeg' => 'JPEG',
);
foreach ($image_type_map as $function => $image_type) {
if (function_exists($function)) {
self::write(" okay Support for '{$image_type}' is available.\n");
} else {
self::write(" warn Support for '{$image_type}' is not available!\n");
$issue_gd_warning = true;
}
}
} else {
self::write(" warn Extension 'gd' is not loaded.\n");
$issue_gd_warning = true;
}
if ($issue_gd_warning) {
self::write(
"[WARN] The 'gd' library is missing or lacks full support. ".
"Phabricator will not be able to generate image thumbnails without ".
"gd.\n");
} else {
self::write("[OKAY] 'gd' loaded and has full image type support.\n");
}
self::writeHeader('FACEBOOK INTEGRATION');
$fb_auth = PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
if (!$fb_auth) {
self::write(" skip 'facebook.auth-enabled' not enabled.\n");
} else {
self::write(" okay 'facebook.auth-enabled' is enabled.\n");
$app_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
$app_secret = PhabricatorEnv::getEnvConfig('facebook.application-secret');
if (!$app_id) {
self::writeFailure();
self::write(
"Setup failure! 'facebook.auth-enabled' is true but there is no ".
"setting for 'facebook.application-id'.\n");
return;
} else {
self::write(" okay 'facebook.application-id' is set.\n");
}
if (!is_string($app_id)) {
self::writeFailure();
self::write(
"Setup failure! 'facebook.application-id' should be a string.");
return;
} else {
self::write(" okay 'facebook.application-id' is string.\n");
}
if (!$app_secret) {
self::writeFailure();
self::write(
"Setup failure! 'facebook.auth-enabled' is true but there is no ".
"setting for 'facebook.application-secret'.");
return;
} else {
self::write(" okay 'facebook.application-secret is set.\n");
}
self::write("[OKAY] Facebook integration OKAY\n");
}
self::writeHeader("MySQL DATABASE & STORAGE CONFIGURATION");
$conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
$conn_user = $conf->getUser();
$conn_pass = $conf->getPassword();
$conn_host = $conf->getHost();
$timeout = ini_get('mysql.connect_timeout');
if ($timeout > 5) {
self::writeNote(
"Your MySQL connect timeout is very high ({$timeout} seconds). ".
"Consider reducing it to 5 or below by setting ".
"'mysql.connect_timeout' in your php.ini.");
}
self::write(" okay Trying to connect to MySQL database ".
"{$conn_user}@{$conn_host}...\n");
ini_set('mysql.connect_timeout', 2);
$conn_raw = PhabricatorEnv::newObjectFromConfig(
'mysql.implementation',
array(
array(
'user' => $conn_user,
'pass' => $conn_pass,
'host' => $conn_host,
'database' => null,
),
));
try {
queryfx($conn_raw, 'SELECT 1');
self::write(" okay Connection successful!\n");
} catch (AphrontQueryConnectionException $ex) {
$message = $ex->getMessage();
self::writeFailure();
self::write(
"Setup failure! MySQL exception: {$message} \n".
"Edit Phabricator configuration keys 'mysql.user', ".
"'mysql.host' and 'mysql.pass' to enable Phabricator ".
"to connect.");
return;
}
$engines = queryfx_all($conn_raw, 'SHOW ENGINES');
$engines = ipull($engines, 'Engine', 'Engine');
if (empty($engines['InnoDB'])) {
self::writeFailure();
self::write(
"Setup failure! The 'InnoDB' engine is not available. Enable ".
"InnoDB in your MySQL configuration. If you already created tables, ".
"MySQL incorrectly used some other engine. You need to convert ".
"them or drop and reinitialize them.");
return;
} else {
self::write(" okay InnoDB is available.\n");
}
$databases = queryfx_all($conn_raw, 'SHOW DATABASES');
$databases = ipull($databases, 'Database', 'Database');
if (empty($databases['phabricator_meta_data'])) {
self::writeFailure();
self::write(
"Setup failure! You haven't loaded the 'initialize.sql' file into ".
"MySQL. This file initializes necessary databases. See this guide for ".
"instructions:\n");
self::writeDoc('article/Configuration_Guide.html');
return;
} else {
self::write(" okay Databases have been initialized.\n");
}
$schema_version = queryfx_one(
$conn_raw,
'SELECT version FROM phabricator_meta_data.schema_version');
$schema_version = idx($schema_version, 'version', 'null');
$expect = PhabricatorSQLPatchList::getExpectedSchemaVersion();
if ($schema_version != $expect) {
self::writeFailure();
self::write(
"Setup failure! You haven't upgraded your database schema to the ".
"latest version. Expected version is '{$expect}', but your local ".
"version is '{$schema_version}'. See this guide for instructions:\n");
self::writeDoc('article/Upgrading_Schema.html');
return;
} else {
self::write(" okay Database schema are up to date (v{$expect}).\n");
}
$index_min_length = queryfx_one(
$conn_raw,
'SHOW VARIABLES LIKE %s',
'ft_min_word_len');
$index_min_length = idx($index_min_length, 'Value', 4);
if ($index_min_length >= 4) {
self::writeNote(
"MySQL is configured with a 'ft_min_word_len' of 4 or greater, which ".
"means you will not be able to search for 3-letter terms. Consider ".
"setting this in your configuration:\n".
"\n".
" [mysqld]\n".
" ft_min_word_len=3\n".
"\n".
"Then optionally run:\n".
"\n".
" REPAIR TABLE phabricator_search.search_documentfield QUICK;\n".
"\n".
"...to reindex existing documents.");
}
$max_allowed_packet = queryfx_one(
$conn_raw,
'SHOW VARIABLES LIKE %s',
'max_allowed_packet');
$max_allowed_packet = idx($max_allowed_packet, 'Value', PHP_INT_MAX);
$recommended_minimum = 1024 * 1024;
if ($max_allowed_packet < $recommended_minimum) {
self::writeNote(
"MySQL is configured with a small 'max_allowed_packet' ".
"('{$max_allowed_packet}'), which may cause some large writes to ".
"fail. Consider raising this to at least {$recommended_minimum}.");
} else {
self::write(" okay max_allowed_packet = {$max_allowed_packet}.\n");
}
$mysql_key = 'storage.mysql-engine.max-size';
$mysql_limit = PhabricatorEnv::getEnvConfig($mysql_key);
if ($mysql_limit && ($mysql_limit + 8192) > $max_allowed_packet) {
self::writeFailure();
self::write(
"Setup failure! Your Phabricator 'storage.mysql-engine.max-size' ".
"configuration ('{$mysql_limit}') must be at least 8KB smaller ".
"than your MySQL 'max_allowed_packet' configuration ".
"('{$max_allowed_packet}'). Raise the 'max_allowed_packet' in your ".
"MySQL configuration, or reduce the maximum file size allowed by ".
"the Phabricator configuration.\n");
return;
} else if (!$mysql_limit) {
self::write(" skip MySQL file storage engine not configured.\n");
} else {
self::write(" okay MySQL file storage engine configuration okay.\n");
}
$local_key = 'storage.local-disk.path';
$local_path = PhabricatorEnv::getEnvConfig($local_key);
if ($local_path) {
if (!Filesystem::pathExists($local_path) ||
!is_readable($local_path) ||
!is_writable($local_path)) {
self::writeFailure();
self::write(
"Setup failure! You have configured local disk storage but the ".
"path you specified ('{$local_path}') does not exist or is not ".
"readable or writable.\n");
if ($open_basedir) {
self::write(
"You have an 'open_basedir' setting -- make sure Phabricator is ".
"allowed to open files in the local storage directory.\n");
}
return;
} else {
self::write(" okay Local disk storage exists and is writable.\n");
}
} else {
self::write(" skip Not configured for local disk storage.\n");
}
$selector = PhabricatorEnv::getEnvConfig('storage.engine-selector');
try {
$storage_selector_exists = class_exists($selector);
} catch (Exception $ex) {
$storage_selector_exists = false;
}
if ($storage_selector_exists) {
self::write(" okay Using '{$selector}' as a storage engine selector.\n");
} else {
self::writeFailure();
self::write(
"Setup failure! You have configured '{$selector}' as a storage engine ".
"selector but it does not exist or could not be loaded.\n");
return;
}
self::write("[OKAY] Database and storage configuration OKAY\n");
self::writeHeader("OUTBOUND EMAIL CONFIGURATION");
$have_adapter = false;
$is_ses = false;
$adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter');
switch ($adapter) {
case 'PhabricatorMailImplementationPHPMailerLiteAdapter':
$have_adapter = true;
if (!Filesystem::pathExists('/usr/bin/sendmail') &&
!Filesystem::pathExists('/usr/sbin/sendmail')) {
self::writeFailure();
self::write(
"Setup failure! You don't have a 'sendmail' binary on this system ".
"but outbound email is configured to use sendmail. Install an MTA ".
"(like sendmail, qmail or postfix) or use a different outbound ".
"mail configuration. See this guide for configuring outbound ".
"email:\n");
self::writeDoc('article/Configuring_Outbound_Email.html');
return;
} else {
self::write(" okay Sendmail is configured.\n");
}
break;
case 'PhabricatorMailImplementationAmazonSESAdapter':
$is_ses = true;
$have_adapter = true;
if (PhabricatorEnv::getEnvConfig('metamta.can-send-as-user')) {
self::writeFailure();
self::write(
"Setup failure! 'metamta.can-send-as-user' must be false when ".
"configured with Amazon SES.");
return;
} else {
self::write(" okay Sender config looks okay.\n");
}
if (!PhabricatorEnv::getEnvConfig('amazon-ses.access-key')) {
self::writeFailure();
self::write(
"Setup failure! 'amazon-ses.access-key' is not set, but ".
"outbound mail is configured to deliver via Amazon SES.");
return;
} else {
self::write(" okay Amazon SES access key is set.\n");
}
if (!PhabricatorEnv::getEnvConfig('amazon-ses.secret-key')) {
self::writeFailure();
self::write(
"Setup failure! 'amazon-ses.secret-key' is not set, but ".
"outbound mail is configured to deliver via Amazon SES.");
return;
} else {
self::write(" okay Amazon SES secret key is set.\n");
}
if (PhabricatorEnv::getEnvConfig('metamta.send-immediately')) {
self::writeNote(
"Your configuration uses Amazon SES to deliver email but tries ".
"to send it immediately. This will work, but it's slow. ".
"Consider configuring the MetaMTA daemon.");
}
break;
case 'PhabricatorMailImplementationTestAdapter':
self::write(" skip You have disabled outbound email.\n");
break;
default:
self::write(" skip Configured with a custom adapter.\n");
break;
}
if ($have_adapter) {
$default = PhabricatorEnv::getEnvConfig('metamta.default-address');
if (!$default || $default == 'noreply@example.com') {
self::writeFailure();
self::write(
"Setup failure! You have not set 'metamta.default-address'.");
return;
} else {
self::write(" okay metamta.default-address is set.\n");
}
if ($is_ses) {
self::writeNote(
"Make sure you've verified your 'from' address ('{$default}') with ".
"Amazon SES. Until you verify it, you will be unable to send mail ".
"using Amazon SES.");
}
$domain = PhabricatorEnv::getEnvConfig('metamta.domain');
if (!$domain || $domain == 'example.com') {
self::writeFailure();
self::write(
"Setup failure! You have not set 'metamta.domain'.");
return;
} else {
self::write(" okay metamta.domain is set.\n");
}
self::write("[OKAY] Mail configuration OKAY\n");
}
self::writeHeader('CONFIG CLASSES');
foreach (PhabricatorEnv::getRequiredClasses() as $key => $instanceof) {
$config = PhabricatorEnv::getEnvConfig($key);
if (!$config) {
self::writeNote("'$key' is not set.");
} else {
try {
$r = new ReflectionClass($config);
if (!$r->isSubclassOf($instanceof)) {
throw new Exception(
"Config setting '$key' must be an instance of '$instanceof'.");
} else if (!$r->isInstantiable()) {
throw new Exception("Config setting '$key' must be instantiable.");
}
} catch (Exception $ex) {
self::writeFailure();
self::write("Setup failure! ".$ex->getMessage());
return;
}
}
}
self::write("[OKAY] Config classes OKAY\n");
self::writeHeader('SUCCESS!');
self::write(
"Congratulations! Your setup seems mostly correct, or at least fairly ".
"reasonable.\n\n".
"*** NEXT STEP ***\n".
"Edit your configuration file (conf/{$env}.conf.php) and remove the ".
"'phabricator.setup' line to finish installation.");
}
public static function requireExtension($extension) {
if (extension_loaded($extension)) {
self::write(" okay Extension '{$extension}' installed.\n");
return true;
} else {
self::write("[FAIL] Extension '{$extension}' is NOT INSTALLED!\n");
return false;
}
}
private static function writeFailure() {
self::write("\n\n<<< *** FAILURE! *** >>>\n");
}
private static function write($str) {
echo $str;
ob_flush();
flush();
// This, uh, makes it look cool. -_-
usleep(20000);
}
private static function writeNote($note) {
$note = "*** NOTE: ".wordwrap($note, 75, "\n", true);
$note = "\n".str_replace("\n", "\n ", $note)."\n\n";
self::write($note);
}
public static function writeHeader($header) {
$template = '>>>'.str_repeat('-', 77);
$template = substr_replace(
$template,
' '.$header.' ',
3,
strlen($header) + 4);
self::write("\n\n{$template}\n\n");
}
public static function writeDoc($doc) {
self::write(
"\n".
- ' http://phabricator.com/docs/phabricator/'.$doc.
+ ' http://www.phabricator.com/docs/phabricator/'.$doc.
"\n\n");
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Dec 3, 10:22 AM (9 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
433277
Default Alt Text
(48 KB)

Event Timeline