1: <?php
2: /*
3: You may not change or alter any portion of this comment or credits
4: of supporting developers from this source code or any supporting source code
5: which is considered copyrighted (c) material of the original comment or credit authors.
6:
7: This program is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY; without even the implied warranty of
9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10: */
11:
12: /**
13: * Installer mainfile creation page
14: *
15: * See the enclosed file license.txt for licensing information.
16: * If you did not receive this file, get it at https://www.gnu.org/licenses/gpl-2.0.html
17: *
18: * @copyright (c) 2000-2021 XOOPS Project (www.xoops.org)
19: * @license GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
20: * @package installer
21: * @since 2.3.0
22: * @author Haruki Setoyama <haruki@planewave.org>
23: * @author Kazumi Ono <webmaster@myweb.ne.jp>
24: * @author Skalpa Keo <skalpa@xoops.org>
25: * @author Taiwen Jiang <phppp@users.sourceforge.net>
26: * @author DuGris (aka L. JEN) <dugris@frxoops.org>
27: **/
28:
29: require_once __DIR__ . '/include/common.inc.php';
30: defined('XOOPS_INSTALL') || die('XOOPS Installation wizard die');
31:
32: $pageHasForm = false;
33: $pageHasHelp = false;
34:
35: $vars =& $_SESSION['settings'];
36:
37: if (empty($vars['ROOT_PATH'])) {
38: $wizard->redirectToPage('pathsettings');
39: exit();
40: } elseif (empty($vars['DB_HOST'])) {
41: $wizard->redirectToPage('dbsettings');
42: exit();
43: }
44:
45: $writeFiles = array(
46: $vars['ROOT_PATH'] . '/mainfile.php',
47: $vars['VAR_PATH'] . '/data/secure.php',
48: );
49:
50: $writeCheck = checkFileWriteablity($writeFiles);
51: if (true === $writeCheck) {
52: $rewrite = array(
53: 'GROUP_ADMIN' => 1,
54: 'GROUP_USERS' => 2,
55: 'GROUP_ANONYMOUS' => 3);
56: $rewrite = array_merge($rewrite, $vars);
57:
58: $result = writeConfigurationFile($rewrite, $vars['VAR_PATH'] . '/data', 'secure.dist.php', 'secure.php');
59: $GLOBALS['error'] = ($result !== true);
60: if ($result === true) {
61: $result = copyConfigDistFiles($vars);
62: $GLOBALS['error'] = ($result !== true);
63: }
64: if ($result === true) {
65: $result = writeConfigurationFile($rewrite, $vars['ROOT_PATH'], 'mainfile.dist.php', 'mainfile.php');
66: $GLOBALS['error'] = ($result !== true);
67: }
68:
69: $_SESSION['settings']['authorized'] = false;
70:
71: if ($result === true) {
72: $_SESSION['UserLogin'] = true;
73: $_SESSION['settings']['authorized'] = true;
74: ob_start();
75: ?>
76:
77: <div class="alert alert-success"><span class="fa fa-check text-success"></span> <?php echo SAVED_MAINFILE; ?></div>
78: <div class='well'><?php echo SAVED_MAINFILE_MSG; ?>
79: <ul class='diags'>
80: <?php
81: foreach ($vars as $k => $v) {
82: if ($k === 'authorized') {
83: continue;
84: }
85: echo "<li><strong>XOOPS_{$k}</strong> " . IS_VALOR . " {$v}</li>";
86: }
87: ?>
88: </ul>
89: </div>
90: <?php
91: $content = ob_get_contents();
92: ob_end_clean();
93: } else {
94: $GLOBALS['error'] = true;
95: $pageHasForm = true; // will redirect to same page
96: $content = '<div class="alert alert-danger"><span class="fa fa-ban text-danger"></span> ' . $result . '</div>';
97: }
98: } else {
99: $content = '';
100: foreach ($writeCheck as $errorMsg) {
101: $GLOBALS['error'] = true;
102: $pageHasForm = true; // will redirect to same page
103: $content .= '<div class="alert alert-danger"><span class="fa fa-ban text-danger"></span> ' . $errorMsg . '</div>' . "\n";
104: }
105: }
106: include __DIR__ . '/include/install_tpl.php';
107:
108: /**
109: * Copy a configuration file from template, then rewrite with actual configuration values
110: *
111: * @param string[] $vars config values
112: * @param string $path directory path where files reside
113: * @param string $sourceName template file name
114: * @param string $fileName configuration file name
115: *
116: * @return true|string true on success, error message on failure
117: */
118: function writeConfigurationFile($vars, $path, $sourceName, $fileName)
119: {
120: $path .= '/';
121: if (!@copy($path . $sourceName, $path . $fileName)) {
122: return sprintf(ERR_COPY_MAINFILE, $fileName);
123: } else {
124: clearstatcache();
125: if (!$file = fopen($path . $fileName, 'r')) {
126: return sprintf(ERR_READ_MAINFILE, $fileName);
127: } else {
128: $content = fread($file, filesize($path . $fileName));
129: fclose($file);
130:
131: foreach ($vars as $key => $val) {
132: if ($key === 'XOOPS_URL') {
133: $content = preg_replace("/(define\()([\"'])(XOOPS_{$key})\\2,\s*([\"'])(.*?)\\4\s*\)/", "define('XOOPS_{$key}', XOOPS_PROT . {$val})", $content);
134: continue;
135: }
136: if (is_int($val) && preg_match("/(define\()([\"'])(XOOPS_{$key})\\2,\s*(\d+)\s*\)/", $content)) {
137: $content = preg_replace("/(define\()([\"'])(XOOPS_{$key})\\2,\s*(\d+)\s*\)/", "define('XOOPS_{$key}', {$val})", $content);
138: } elseif (preg_match("/(define\()([\"'])(XOOPS_{$key})\\2,\s*([\"'])(.*?)\\4\s*\)/", $content)) {
139: $val = str_replace('$', '\$', addslashes($val));
140: $content = preg_replace("/(define\()([\"'])(XOOPS_{$key})\\2,\s*([\"'])(.*?)\\4\s*\)/", "define('XOOPS_{$key}', '{$val}')", $content);
141: }
142: }
143: $file = fopen($path . $fileName, 'w');
144: if (false === $file) {
145: return sprintf(ERR_WRITE_MAINFILE, $fileName);
146: }
147: $writeResult = fwrite($file, $content);
148: fclose($file);
149: if (false === $writeResult) {
150: return sprintf(ERR_WRITE_MAINFILE, $fileName);
151: }
152: }
153: }
154: return true;
155: }
156:
157:
158: /**
159: * Get file stats
160: *
161: * @param string $filename file or directory name
162: *
163: * @return array|false false on error, or array of file stat information
164: */
165: function getStats($filename)
166: {
167: $stat = stat($filename);
168: if (false === $stat) {
169: return false;
170: }
171: return prepStats($stat);
172: }
173:
174: /**
175: * Get file stats on a created temp file
176: *
177: * @return array|false false on error, or array of file stat information
178: */
179: function getTmpStats()
180: {
181: $temp = tmpfile();
182: if (false === $temp) {
183: return false;
184: }
185: $stat = fstat($temp);
186: fclose($temp);
187: if (false === $stat) {
188: return false;
189: }
190: return prepStats($stat);
191: }
192:
193: /**
194: * Get stat() info in a more usable form
195: *
196: * @param array $stat return from PHP stat()
197: *
198: * @return array selected information gleaned from $stat
199: */
200: function prepStats($stat)
201: {
202: $subSet = array();
203: $mode = $stat['mode'];
204: $subSet['mode'] = $mode;
205: $subSet['uid'] = $stat['uid'];
206: $subSet['gid'] = $stat['gid'];
207:
208: $subSet['user']['read'] = (bool) ($mode & 0400);
209: $subSet['user']['write'] = (bool) ($mode & 0200);
210: $subSet['user']['exec'] = (bool) ($mode & 0100);
211: $subSet['group']['read'] = (bool) ($mode & 040);
212: $subSet['group']['write'] = (bool) ($mode & 020);
213: $subSet['group']['exec'] = (bool) ($mode & 010);
214: $subSet['other']['read'] = (bool) ($mode & 04);
215: $subSet['other']['write'] = (bool) ($mode & 02);
216: $subSet['other']['exec'] = (bool) ($mode & 01);
217:
218: return $subSet;
219: }
220:
221: /**
222: * Attempt to check if a set of files can be written
223: *
224: * @param string[] $files fully qualified file names to check
225: *
226: * @return string[]|true true if no issues found, array
227: */
228: function checkFileWriteablity($files)
229: {
230: if (isset($_POST['op']) && $_POST['op'] === 'proceed') {
231: return true; // user said skip this
232: }
233: $tmpStats = getTmpStats();
234: if (false === $tmpStats) {
235: return true; // tests are not applicable
236: }
237:
238: $message = array();
239:
240: foreach ($files as $file) {
241: $dirName = dirname($file);
242: $fileName = basename($file);
243: $dirStat = getStats($dirName);
244: if (false !== $dirStat) {
245: $uid = $tmpStats['uid'];
246: $gid = $tmpStats['gid'];
247: if (!(($uid === $dirStat['uid'] && $dirStat['user']['write'])
248: || ($gid === $dirStat['gid'] && $dirStat['group']['write'])
249: || (file_exists($file) && is_writable($file))
250: || (false !== stripos(PHP_OS, 'WIN'))
251: )
252: ) {
253: $uidStr = (string) $uid;
254: $dUidStr = (string) $dirStat['uid'];
255: $gidStr = (string) $gid;
256: $dGidStr = (string) $dirStat['gid'];
257: if (function_exists('posix_getpwuid')) {
258: $tempUsr = posix_getpwuid($uid);
259: $uidStr = isset($tempUsr['name']) ? $tempUsr['name'] : (string) $uid;
260: $tempUsr = posix_getpwuid($dirStat['uid']);
261: $dUidStr = isset($tempUsr['name']) ? $tempUsr['name'] : (string) $dirStat['uid'];
262: }
263: if (function_exists('posix_getgrgid')) {
264: $tempGrp = posix_getgrgid($gid);
265: $gidStr = isset($tempGrp['name']) ? $tempGrp['name'] : (string) $gid;
266: $tempGrp = posix_getgrgid($dirStat['gid']);
267: $dGidStr = isset($tempGrp['name']) ? $tempGrp['name'] : (string) $dirStat['gid'];
268: }
269: $message[] = sprintf(
270: CHMOD_CHGRP_ERROR,
271: $fileName,
272: $uidStr,
273: $gidStr,
274: basename($dirName),
275: $dUidStr,
276: $dGidStr
277: );
278: }
279: }
280: }
281: return empty($message) ? true : $message;
282: }
283:
284: /**
285: * Install working versions of various *.dist.php files to xoops_data/configs/
286: *
287: * @param $vars array of system variables, we care about ROOT_PATH and VAR_PATH keys
288: *
289: * @return true|string true if all files were copied, otherwise error message
290: */
291: function copyConfigDistFiles($vars)
292: {
293: $copied = 0;
294: $failed = 0;
295: $logs = array();
296:
297: /* xoopsconfig.php */
298: $source = $vars['VAR_PATH'] . '/configs/xoopsconfig.dist.php';
299: $destination = $vars['VAR_PATH'] . '/configs/xoopsconfig.php';
300: if (!file_exists($destination)) { // don't overwrite anything
301: $result = copy($source, $destination);
302: $result ? ++$copied : ++$failed;
303: if (false === $result) {
304: $logs[] = sprintf(ERR_COPY_CONFIG_FILE, 'configs/' . basename($destination));
305: }
306: }
307:
308: /* captcha files */
309: $captchaConfigFiles = array(
310: 'config.dist.php' => 'config.php',
311: 'config.image.dist.php' => 'config.image.php',
312: 'config.recaptcha2.dist.php' => 'config.recaptcha2.php',
313: 'config.text.dist.php' => 'config.text.php',
314: );
315:
316: foreach ($captchaConfigFiles as $source => $destination) {
317: $src = $vars['ROOT_PATH'] . '/class/captcha/' . $source;
318: $dest = $vars['VAR_PATH'] . '/configs/captcha/' . $destination;
319: if (!file_exists($dest) && file_exists($src)) {
320: $result = copy($src, $dest);
321: $result ? ++$copied : ++$failed;
322: if (false === $result) {
323: $logs[] = sprintf('captcha config file copy to %s failed', $destination);
324: $logs[] = sprintf(ERR_COPY_CONFIG_FILE, 'captcha/' . $destination);
325: }
326: }
327: }
328:
329: /* text sanitizer files */
330: $textsanitizerConfigFiles = array(
331: 'config.dist.php' => 'config.php',
332: 'censor/config.dist.php' => 'config.censor.php',
333: 'flash/config.dist.php' => 'config.flash.php',
334: 'image/config.dist.php' => 'config.image.php',
335: 'mms/config.dist.php' => 'config.mms.php',
336: 'rtsp/config.dist.php' => 'config.rtsp.php',
337: 'syntaxhighlight/config.dist.php' => 'config.syntaxhighlight.php',
338: 'textfilter/config.dist.php' => 'config.textfilter.php',
339: 'wiki/config.dist.php' => 'config.wiki.php',
340: 'wmp/config.dist.php' => 'config.wmp.php',
341: );
342: foreach ($textsanitizerConfigFiles as $source => $destination) {
343: $src = $vars['ROOT_PATH'] . '/class/textsanitizer/' . $source;
344: $dest = $vars['VAR_PATH'] . '/configs/textsanitizer/' . $destination;
345: if (!file_exists($dest) && file_exists($src)) {
346: $result = copy($src, $dest);
347: $result ? ++$copied : ++$failed;
348: if (false === $result) {
349: $logs[] = sprintf(ERR_COPY_CONFIG_FILE, 'textsanitizer/' . $destination);
350: }
351: }
352: }
353:
354: return $failed === 0 ? true : implode('<br>', $logs);
355: }
356: