Completed
Pull Request — master (#545)
by Richard
09:25
created

PathStuffController::checkPath()   C

Complexity

Conditions 15
Paths 36

Size

Total Lines 30
Code Lines 20

Duplication

Lines 14
Ratio 46.67 %

Importance

Changes 0
Metric Value
cc 15
eloc 20
nc 36
nop 1
dl 14
loc 30
rs 5.0504
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * See the enclosed file license.txt for licensing information.
5
 * If you did not receive this file, get it at http://www.gnu.org/licenses/gpl-2.0.html
6
 *
7
 * @copyright    (c) 2000-2016 XOOPS Project (www.xoops.org)
8
 * @license          GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
9
 * @package          installer
10
 * @since            2.3.0
11
 * @author           Haruki Setoyama  <[email protected]>
12
 * @author           Kazumi Ono <[email protected]>
13
 * @author           Skalpa Keo <[email protected]>
14
 * @author           Taiwen Jiang <[email protected]>
15
 * @author           DuGris (aka L. JEN) <[email protected]>
16
 **/
17
class PathStuffController
18
{
19
    public $xoopsPath = array(
20
        'root' => '',
21
        'lib'  => '',
22
        'data' => '');
23
24
    public $xoopsPathDefault = array(
25
        'lib'  => 'xoops_lib',
26
        'data' => 'xoops_data');
27
28
    public $dataPath = array(
29
        'caches' => array(
30
            'xoops_cache',
31
            'smarty_cache',
32
            'smarty_compile'),
33
        'configs');
34
35
    public $path_lookup = array(
36
        'root' => 'ROOT_PATH',
37
        'data' => 'VAR_PATH',
38
        'lib'  => 'PATH');
39
40
    public $xoopsUrl = '';
41
    public $xoopsCookieDomain = '';
42
43
    public $validPath = array(
44
        'root' => 0,
45
        'data' => 0,
46
        'lib'  => 0);
47
48
    public $validUrl = false;
49
50
    public $permErrors = array(
51
        'root' => null,
52
        'data' => null);
53
54
    /**
55
     * @param $xoopsPathDefault
56
     * @param $dataPath
57
     */
58
    public function __construct($xoopsPathDefault, $dataPath)
59
    {
60
        $this->xoopsPathDefault = $xoopsPathDefault;
61
        $this->dataPath         = $dataPath;
62
63
        if (isset($_SESSION['settings']['ROOT_PATH'])) {
64
            foreach ($this->path_lookup as $req => $sess) {
65
                $this->xoopsPath[$req] = $_SESSION['settings'][$sess];
66
            }
67
        } else {
68
            $path = str_replace("\\", '/', realpath('../'));
69 View Code Duplication
            if (substr($path, -1) === '/') {
70
                $path = substr($path, 0, -1);
71
            }
72
            if (file_exists("$path/mainfile.dist.php")) {
73
                $this->xoopsPath['root'] = $path;
74
            }
75
            // Firstly, locate XOOPS lib folder out of XOOPS root folder
76
            $this->xoopsPath['lib'] = dirname($path) . '/' . $this->xoopsPathDefault['lib'];
77
            // If the folder is not created, re-locate XOOPS lib folder inside XOOPS root folder
78 View Code Duplication
            if (!is_dir($this->xoopsPath['lib'] . '/')) {
79
                $this->xoopsPath['lib'] = $path . '/' . $this->xoopsPathDefault['lib'];
80
            }
81
            // Firstly, locate XOOPS data folder out of XOOPS root folder
82
            $this->xoopsPath['data'] = dirname($path) . '/' . $this->xoopsPathDefault['data'];
83
            // If the folder is not created, re-locate XOOPS data folder inside XOOPS root folder
84 View Code Duplication
            if (!is_dir($this->xoopsPath['data'] . '/')) {
85
                $this->xoopsPath['data'] = $path . '/' . $this->xoopsPathDefault['data'];
86
            }
87
        }
88
        if (isset($_SESSION['settings']['URL'])) {
89
            $this->xoopsUrl = $_SESSION['settings']['URL'];
90
        } else {
91
            $path           = $GLOBALS['wizard']->baseLocation();
92
            $this->xoopsUrl = substr($path, 0, strrpos($path, '/'));
93
        }
94
        if (isset($_SESSION['settings']['COOKIE_DOMAIN'])) {
95
            $this->xoopsCookieDomain = $_SESSION['settings']['COOKIE_DOMAIN'];
96
        } else {
97
            $this->xoopsCookieDomain = xoops_getBaseDomain($this->xoopsUrl);
98
        }
99
    }
100
101
    public function execute()
102
    {
103
        $this->readRequest();
104
        $valid = $this->validate();
105
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
106
            foreach ($this->path_lookup as $req => $sess) {
107
                $_SESSION['settings'][$sess] = $this->xoopsPath[$req];
108
            }
109
            $_SESSION['settings']['URL'] = $this->xoopsUrl;
110
            $_SESSION['settings']['COOKIE_DOMAIN'] = $this->xoopsCookieDomain;
111
            if ($valid) {
112
                $GLOBALS['wizard']->redirectToPage('+1');
113
            } else {
114
                $GLOBALS['wizard']->redirectToPage('+0');
115
            }
116
        }
117
    }
118
119
    public function readRequest()
120
    {
121
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
122
            $request = $_POST;
123
            foreach ($this->path_lookup as $req => $sess) {
124
                if (isset($request[$req])) {
125
                    $request[$req] = str_replace("\\", '/', trim($request[$req]));
126
                    if (substr($request[$req], -1) === '/') {
127
                        $request[$req] = substr($request[$req], 0, -1);
128
                    }
129
                    $this->xoopsPath[$req] = $request[$req];
130
                }
131
            }
132
            if (isset($request['URL'])) {
133
                $request['URL'] = trim($request['URL']);
134
                if (substr($request['URL'], -1) === '/') {
135
                    $request['URL'] = substr($request['URL'], 0, -1);
136
                }
137
                $this->xoopsUrl = $request['URL'];
138
            }
139
            if (isset($request['COOKIE_DOMAIN'])) {
140
                $tempCookieDomain = trim($request['COOKIE_DOMAIN']);
141
                $tempParts = parse_url($tempCookieDomain);
142
                if (!empty($tempParts['host'])) {
143
                    $tempCookieDomain = $tempParts['host'];
144
                }
145
                $request['COOKIE_DOMAIN'] = $tempCookieDomain;
146
                $this->xoopsCookieDomain = $tempCookieDomain;;
147
            }
148
        }
149
    }
150
151
    /**
152
     * @return bool
153
     */
154
    public function validate()
155
    {
156
        foreach (array_keys($this->xoopsPath) as $path) {
157
            if ($this->checkPath($path)) {
158
                $this->checkPermissions($path);
159
            }
160
        }
161
        $this->validUrl = !empty($this->xoopsUrl);
162
        $validPaths     = (array_sum(array_values($this->validPath)) == count(array_keys($this->validPath))) ? 1 : 0;
163
        $validPerms     = true;
164
        foreach ($this->permErrors as $key => $errs) {
165
            if (empty($errs)) {
166
                continue;
167
            }
168
            foreach ($errs as $path => $status) {
169
                if (empty($status)) {
170
                    $validPerms = false;
171
                    break;
172
                }
173
            }
174
        }
175
176
        return ($validPaths && $this->validUrl && $validPerms);
177
    }
178
179
    /**
180
     * @param string $PATH
181
     *
182
     * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
183
     */
184
    public function checkPath($PATH = '')
185
    {
186
        $ret = 1;
187
        if ($PATH === 'root' || empty($PATH)) {
188
            $path = 'root';
189
            if (is_dir($this->xoopsPath[$path]) && is_readable($this->xoopsPath[$path])) {
190
                @include_once "{$this->xoopsPath[$path]}/include/version.php";
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
191
                if (file_exists("{$this->xoopsPath[$path]}/mainfile.dist.php") && defined('XOOPS_VERSION')) {
192
                    $this->validPath[$path] = 1;
193
                }
194
            }
195
            $ret *= $this->validPath[$path];
196
        }
197 View Code Duplication
        if ($PATH === 'lib' || empty($PATH)) {
198
            $path = 'lib';
199
            if (is_dir($this->xoopsPath[$path]) && is_readable($this->xoopsPath[$path])) {
200
                $this->validPath[$path] = 1;
201
            }
202
            $ret *= $this->validPath[$path];
203
        }
204 View Code Duplication
        if ($PATH === 'data' || empty($PATH)) {
205
            $path = 'data';
206
            if (is_dir($this->xoopsPath[$path]) && is_readable($this->xoopsPath[$path])) {
207
                $this->validPath[$path] = 1;
208
            }
209
            $ret *= $this->validPath[$path];
210
        }
211
212
        return $ret;
213
    }
214
215
    /**
216
     * @param $parent
217
     * @param $path
218
     * @param $error
219
     * @return null
220
     */
221
    public function setPermission($parent, $path, &$error)
222
    {
223
        if (is_array($path)) {
224
            foreach (array_keys($path) as $item) {
225
                if (is_string($item)) {
226
                    $error[$parent . '/' . $item] = $this->makeWritable($parent . '/' . $item);
227
                    if (empty($path[$item])) {
228
                        continue;
229
                    }
230
                    foreach ($path[$item] as $child) {
231
                        $this->setPermission($parent . '/' . $item, $child, $error);
232
                    }
233
                } else {
234
                    $error[$parent . '/' . $path[$item]] = $this->makeWritable($parent . '/' . $path[$item]);
235
                }
236
            }
237
        } else {
238
            $error[$parent . '/' . $path] = $this->makeWritable($parent . '/' . $path);
239
        }
240
241
        return null;
242
    }
243
244
    /**
245
     * @param $path
246
     *
247
     * @return bool
248
     */
249
    public function checkPermissions($path)
250
    {
251
        $paths  = array(
252
            'root' => array('mainfile.php', 'uploads', /*'templates_c', 'cache'*/),
253
            'data' => $this->dataPath);
254
        $errors = array(
255
            'root' => null,
256
            'data' => null);
257
258
        if (!isset($this->xoopsPath[$path])) {
259
            return false;
260
        }
261
        if (!isset($errors[$path])) {
262
            return true;
263
        }
264
        $this->setPermission($this->xoopsPath[$path], $paths[$path], $errors[$path]);
265
        if (in_array(false, $errors[$path])) {
266
            $this->permErrors[$path] = $errors[$path];
267
        }
268
269
        return true;
270
    }
271
272
    /**
273
     * Write-enable the specified folder
274
     *
275
     * @param string $path
276
     * @param bool   $create
277
     *
278
     * @internal param bool $recurse
279
     * @return false on failure, method (u-ser,g-roup,w-orld) on success
0 ignored issues
show
Documentation introduced by
Should the return type not be false|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
280
     */
281
    public function makeWritable($path, $create = true)
282
    {
283
        $mode = intval('0777', 8);
284
        if (!file_exists($path)) {
285
            if (!$create) {
286
                return false;
287
            } else {
288
                mkdir($path, $mode);
289
            }
290
        }
291
        if (!is_writable($path)) {
292
            chmod($path, $mode);
293
        }
294
        clearstatcache();
295
        if (is_writable($path)) {
296
            $info = stat($path);
297
            if ($info['mode'] & 0002) {
298
                return 'w';
299
            } elseif ($info['mode'] & 0020) {
300
                return 'g';
301
            }
302
303
            return 'u';
304
        }
305
306
        return false;
307
    }
308
}
309