Skip to content

Commit 77401c7

Browse files
committed
feat: add CheckPhpIni class
1 parent f40b371 commit 77401c7

File tree

2 files changed

+208
-0
lines changed

2 files changed

+208
-0
lines changed

system/Security/CheckPhpIni.php

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Security;
13+
14+
use CodeIgniter\CLI\CLI;
15+
16+
/**
17+
* Checks php.ini settings
18+
*
19+
* @used-by \CodeIgniter\Commands\Utilities\PhpIniCheck
20+
*/
21+
class CheckPhpIni
22+
{
23+
/**
24+
* @param bool $isCli Set false if you run via Web
25+
*
26+
* @return string|void HTML string or void in CLI
27+
*/
28+
public static function run(bool $isCli = true)
29+
{
30+
$output = static::checkIni();
31+
32+
$thead = ['Directive', 'Global', 'Current', 'Recommended', 'Remark'];
33+
$tbody = [];
34+
35+
// CLI
36+
if ($isCli) {
37+
self::outputForCli($output, $thead, $tbody);
38+
39+
return;
40+
}
41+
42+
// Web
43+
return self::outputForWeb($output, $thead, $tbody);
44+
}
45+
46+
private static function outputForCli(array $output, array $thead, array $tbody): void
47+
{
48+
foreach ($output as $directive => $values) {
49+
$current = $values['current'];
50+
$notRecommended = false;
51+
52+
if ($values['recommended'] !== '') {
53+
if ($values['recommended'] !== $values['current']) {
54+
$notRecommended = true;
55+
}
56+
57+
$current = $notRecommended
58+
? CLI::color($values['current'] === '' ? 'n/a' : $values['current'], 'red')
59+
: $values['current'];
60+
}
61+
62+
$directive = $notRecommended ? CLI::color($directive, 'red') : $directive;
63+
$tbody[] = [
64+
$directive, $values['global'], $current, $values['recommended'], $values['remark'],
65+
];
66+
}
67+
68+
CLI::table($tbody, $thead);
69+
}
70+
71+
private static function outputForWeb(array $output, array $thead, array $tbody): string
72+
{
73+
foreach ($output as $directive => $values) {
74+
$current = $values['current'];
75+
$notRecommended = false;
76+
77+
if ($values['recommended'] !== '') {
78+
if ($values['recommended'] !== $values['current']) {
79+
$notRecommended = true;
80+
}
81+
82+
if ($values['current'] === '') {
83+
$current = 'n/a';
84+
}
85+
86+
$current = $notRecommended
87+
? '<span style="color: red">' . $current . '</span>'
88+
: $current;
89+
}
90+
91+
$directive = $notRecommended
92+
? '<span style="color: red">' . $directive . '</span>'
93+
: $directive;
94+
$tbody[] = [
95+
$directive, $values['global'], $current, $values['recommended'], $values['remark'],
96+
];
97+
}
98+
99+
$table = new \CodeIgniter\View\Table();
100+
$template = [
101+
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
102+
];
103+
$table->setTemplate($template);
104+
105+
$table->setHeading($thead);
106+
107+
return '<pre>' . $table->generate($tbody) . '</pre>';
108+
}
109+
110+
/**
111+
* @internal Used for testing purposes only.
112+
* @testTag
113+
*/
114+
public static function checkIni(): array
115+
{
116+
$items = [
117+
'error_reporting' => ['recommended' => '5111'],
118+
'display_errors' => ['recommended' => '0'],
119+
'display_startup_errors' => ['recommended' => '0'],
120+
'log_errors' => [],
121+
'error_log' => [],
122+
'default_charset' => ['recommended' => 'UTF-8'],
123+
'memory_limit' => ['remark' => '> post_max_size'],
124+
'post_max_size' => ['remark' => '> upload_max_filesize'],
125+
'upload_max_filesize' => ['remark' => '< post_max_size'],
126+
'request_order' => ['recommended' => 'GP'],
127+
'variables_order' => ['recommended' => 'GPCS'],
128+
'date.timezone' => ['recommended' => 'UTC'],
129+
'mbstring.language' => ['recommended' => 'neutral'],
130+
];
131+
132+
$output = [];
133+
$ini = ini_get_all();
134+
135+
foreach ($items as $key => $values) {
136+
$output[$key] = [
137+
'global' => $ini[$key]['global_value'],
138+
'current' => $ini[$key]['local_value'],
139+
'recommended' => $values['recommended'] ?? '',
140+
'remark' => $values['remark'] ?? '',
141+
];
142+
}
143+
144+
// [directive => [current_value, recommended_value]]
145+
return $output;
146+
}
147+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Security;
13+
14+
use CodeIgniter\CLI\CLI;
15+
use CodeIgniter\Test\CIUnitTestCase;
16+
use CodeIgniter\Test\Mock\MockInputOutput;
17+
18+
/**
19+
* @internal
20+
*
21+
* @group Others
22+
*/
23+
final class CheckPhpIniTest extends CIUnitTestCase
24+
{
25+
public function testCheckIni()
26+
{
27+
$output = CheckPhpIni::checkIni();
28+
29+
$expected = [
30+
'global' => '',
31+
'current' => '1',
32+
'recommended' => '0',
33+
'remark' => '',
34+
];
35+
$this->assertSame($expected, $output['display_errors']);
36+
}
37+
38+
public function testRunCli()
39+
{
40+
// Set MockInputOutput to CLI.
41+
$io = new MockInputOutput();
42+
CLI::setInputOutput($io);
43+
44+
CheckPhpIni::run(true);
45+
46+
// Get the whole output string.
47+
$output = $io->getOutput();
48+
49+
$this->assertStringContainsString('display_errors', $output);
50+
51+
// Remove MockInputOutput.
52+
CLI::resetInputOutput();
53+
}
54+
55+
public function testRunWeb()
56+
{
57+
$output = CheckPhpIni::run(false);
58+
59+
$this->assertStringContainsString('display_errors', $output);
60+
}
61+
}

0 commit comments

Comments
 (0)