@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorPHPPreflightSetupCheck extends PhabricatorSetupCheck {
4
5 public function getDefaultGroup() {
6 return self::GROUP_PHP;
7 }
8
9 public function isPreflightCheck() {
10 return true;
11 }
12
13 protected function executeChecks() {
14 // Check for `disable_functions` or `disable_classes`. Although it's
15 // possible to disable a bunch of functions (say, `array_change_key_case()`)
16 // and classes and still have Phabricator work fine, it's unreasonably
17 // difficult for us to be sure we'll even survive setup if these options
18 // are enabled. Phabricator needs access to the most dangerous functions,
19 // so there is no reasonable configuration value here which actually
20 // provides a benefit while guaranteeing Phabricator will run properly.
21
22 $disable_options = array('disable_functions', 'disable_classes');
23 foreach ($disable_options as $disable_option) {
24 $disable_value = ini_get($disable_option);
25 if ($disable_value) {
26
27 // By default Debian installs the pcntl extension but disables all of
28 // its functions using configuration. Whitelist disabling these
29 // functions so that Debian PHP works out of the box (we do not need to
30 // call these functions from the web UI). This is pretty ridiculous but
31 // it's not the users' fault and they haven't done anything crazy to
32 // get here, so don't make them pay for Debian's unusual choices.
33 // See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=605571
34 $fatal = true;
35 if ($disable_option == 'disable_functions') {
36 $functions = preg_split('/[, ]+/', $disable_value);
37 $functions = array_filter($functions);
38 foreach ($functions as $k => $function) {
39 if (preg_match('/^pcntl_/', $function)) {
40 unset($functions[$k]);
41 }
42 }
43 if (!$functions) {
44 $fatal = false;
45 }
46 }
47
48 if ($fatal) {
49 $message = pht(
50 "You have '%s' enabled in your PHP configuration.\n\n".
51 "This option is not compatible with this software. Remove ".
52 "'%s' from your configuration to continue.",
53 $disable_option,
54 $disable_option);
55
56 $this->newIssue('php.'.$disable_option)
57 ->setIsFatal(true)
58 ->setName(pht('Remove PHP %s', $disable_option))
59 ->setMessage($message)
60 ->addPHPConfig($disable_option);
61 }
62 }
63 }
64
65 // Remove this check once Phorge requires PHP 8. mbstring.func_overload
66 // got deprecated in PHP 7.2.0 and removed in PHP 8.0.0.
67 $overload_option = 'mbstring.func_overload';
68 $func_overload = ini_get($overload_option);
69 if ($func_overload) {
70 $message = pht(
71 "You have '%s' enabled in your PHP configuration.\n\n".
72 'This feature is "highly discouraged" by PHP\'s developers, and '.
73 'has been removed entirely in PHP8.'.
74 "This option is not compatible with this software. Disable ".
75 "'%s' in your PHP configuration to continue.",
76 $overload_option,
77 $overload_option);
78
79 $this->newIssue('php'.$overload_option)
80 ->setIsFatal(true)
81 ->setName(pht('Disable PHP %s', $overload_option))
82 ->setMessage($message)
83 ->addPHPConfig($overload_option);
84 }
85
86 $open_basedir = ini_get('open_basedir');
87 if ($open_basedir && strlen($open_basedir)) {
88 // If `open_basedir` is set, just fatal. It's technically possible for
89 // us to run with certain values of `open_basedir`, but: we can only
90 // raise fatal errors from preflight steps, so we'd have to do this check
91 // in two parts to support fatal and advisory versions; it's much simpler
92 // to just fatal instead of trying to test all the different things we
93 // may need to access in the filesystem; and use of this option seems
94 // rare (particularly in supported environments).
95
96 $message = pht(
97 "Your server is configured with '%s', which prevents this software ".
98 "from opening files it requires access to.\n\n".
99 "Disable this setting to continue.",
100 'open_basedir');
101
102 $issue = $this->newIssue('php.open_basedir')
103 ->setName(pht('Disable PHP %s', 'open_basedir'))
104 ->addPHPConfig('open_basedir')
105 ->setIsFatal(true)
106 ->setMessage($message);
107 }
108
109 }
110}