Completed
Pull Request — master (#20)
by Fredrik
03:15
created

CSource::__construct()   F

Complexity

Conditions 15
Paths 6144

Size

Total Lines 92
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 92
rs 2
cc 15
eloc 65
nc 6144
nop 1

How to fix   Long Method    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
 * Class for display sourcecode.
4
 *
5
 * @author    Mikael Roos, [email protected]
6
 * @copyright Mikael Roos 2010 - 2015
7
 * @link      https://github.com/mosbth/csource
8
 */
9
namespace Mos\Source;
10
11
class CSource
12
{
13
14
    /**
15
   * Properties
16
   */
17
    private $options = [];
18
19
    /**
20
   * Constructor
21
   *
22
   * @param array $options to alter the default behaviour.
23
   *
24
   * @SuppressWarnings(PHPMD.CyclomaticComplexity)
25
   * @SuppressWarnings(PHPMD.NPathComplexity)
26
   */
27
    public function __construct($options = [])
28
    {
29
        $default = [
30
            'image_extensions' => ['png', 'jpg', 'jpeg', 'gif', 'ico'],
31
            'spaces_to_replace_tab' => '  ',
32
            'ignore' => ['.', '..', '.git', '.svn', '.netrc', '.ssh'],
33
            'add_ignore' => null, // add array with additional filenames to ignore
34
            'secure_dir' => '.',  // Only display files below this directory
35
            'base_dir'   => '.',  // Which directory to start look in, defaults to current working directory of the actual script.
36
            'query_dir'  => isset($_GET['dir'])  ? strip_tags(trim($_GET['dir']))   : null, // Selected directory as ?dir=xxx
37
            'query_file' => isset($_GET['file']) ? strip_tags(trim($_GET['file']))  : null, // Selected directory as ?dir=xxx
38
            'query_path' => isset($_GET['path']) ? strip_tags(trim($_GET['path']))  : null, // Selected directory as ?dir=xxx
39
        ];
40
41
        // Add more files to ignore
42
        if (isset($options['add_ignore'])) {
43
            $default['ignore'] = array_merge($default['ignore'], $options['add_ignore']);
44
        }
45
46
        $this->options = $options = array_merge($default, $options);
47
48
        //Backwards compatible with source.php query arguments for ?dir=xxx&file=xxx
49
        if (!isset($this->options['query_path'])) {
50
            $this->options['query_path'] = trim($this->options['query_dir'] . '/' . $this->options['query_file'], '/');
51
        }
52
53
        $this->validImageExtensions = $options['image_extensions'];
0 ignored issues
show
Bug introduced by
The property validImageExtensions does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
54
        $this->spaces         = $options['spaces_to_replace_tab'];
0 ignored issues
show
Bug introduced by
The property spaces does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
55
        $this->ignore         = $options['ignore'];
0 ignored issues
show
Bug introduced by
The property ignore does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
56
        $this->secureDir      = realpath($options['secure_dir']);
0 ignored issues
show
Bug introduced by
The property secureDir does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
57
        $this->baseDir        = realpath($options['base_dir']);
0 ignored issues
show
Bug introduced by
The property baseDir does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
58
        $this->queryPath      = $options['query_path'];
0 ignored issues
show
Bug introduced by
The property queryPath does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
59
        $this->suggestedPath  = $this->baseDir . '/' . $this->queryPath;
0 ignored issues
show
Bug introduced by
The property suggestedPath does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
60
        $this->realPath       = realpath($this->suggestedPath);
0 ignored issues
show
Bug introduced by
The property realPath does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
61
        $this->pathinfo       = pathinfo($this->realPath);
0 ignored issues
show
Bug introduced by
The property pathinfo does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
62
        $this->path           = null;
0 ignored issues
show
Bug introduced by
The property path does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
63
64
        // Ensure that extension is always set
65
        if (!isset($this->pathinfo['extension'])) {
66
            $this->pathinfo['extension'] = null;
67
        }
68
69
        if (is_dir($this->realPath)) {
70
            $this->file = null;
0 ignored issues
show
Bug introduced by
The property file does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
71
            $this->extension = null;
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
72
            $this->dir  = $this->realPath;
0 ignored issues
show
Bug introduced by
The property dir does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
73
            $this->path = trim($this->queryPath, '/');
74
        } else if (is_link($this->suggestedPath)) {
75
            $this->pathinfo = pathinfo($this->suggestedPath);
76
            $this->file = $this->pathinfo['basename'];
77
            $this->extension = strtolower($this->pathinfo['extension']);
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
78
            $this->dir  = $this->pathinfo['dirname'];
79
            $this->path = trim(dirname($this->queryPath), '/');
80
        } else if (is_readable($this->realPath)) {
81
            $this->file = basename($this->realPath);
82
            $this->extension = strtolower($this->pathinfo['extension']);
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
83
            $this->dir  = dirname($this->realPath);
84
            $this->path = trim(dirname($this->queryPath), '/');
85
        } else {
86
            $this->file = null;
87
            $this->extension = null;
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
88
            $this->dir  = null;
89
        }
90
91
        if ($this->path == '.') {
92
            $this->path = null;
93
        }
94
95
        $this->breadcrumb = empty($this->path) ? [] : explode('/', $this->path);
0 ignored issues
show
Bug introduced by
The property breadcrumb does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
96
97
        // Check that dir lies below securedir
98
        $this->message = null;
0 ignored issues
show
Bug introduced by
The property message does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
99
        $msg = "<p><i>WARNING: The path you have selected is not a valid path or restricted due to security constraints.</i></p>";
100
        if (substr_compare($this->secureDir, $this->dir, 0, strlen($this->secureDir))) {
101
            $this->file = null;
102
            $this->extension = null;
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
103
            $this->dir  = null;
104
            $this->message = $msg;
105
        }
106
107
        // Check that all parts of the path is valid items
108
        foreach ($this->breadcrumb as $val) {
109
            if (in_array($val, $this->ignore)) {
110
                $this->file = null;
111
                $this->extension = null;
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
112
                $this->dir  = null;
113
                $this->message = $msg;
114
                break;
115
            }
116
        }
117
118
    }
119
120
121
122
    /**
123
   * List the sourcecode.
124
   */
125
    public function view()
126
    {
127
        return $this->getBreadcrumbFromPath()
128
        . $this->message . $this->readCurrentDir() . $this->getFileContent();
129
    }
130
131
132
133
    /**
134
   * Create a breadcrumb of the current dir and path.
135
   */
136
    public function getBreadcrumbFromPath()
137
    {
138
139
        $html  = "<ul class='src-breadcrumb'>\n";
140
        $html .= "<li><a href='?'>" . basename($this->baseDir) . "</a>/</li>";
141
        $path = null;
142
        foreach ($this->breadcrumb as $val) {
143
            $path .= "$val/";
144
            $html .= "<li><a href='?path={$path}'>{$val}</a>/</li>";
145
        }
146
        $html .= "</ul>\n";
147
148
        return $html;
149
    }
150
151
152
153
    /**
154
   * Read all files of the current directory.
155
   */
156
    public function readCurrentDir()
157
    {
158
159
        if (!$this->dir) {
160
            return;
161
        }
162
163
        $html = "<ul class='src-filelist'>";
164
        foreach (glob($this->dir . '/{*,.?*}', GLOB_MARK | GLOB_BRACE) as $val) {
165
166
            if (in_array(basename($val), $this->ignore)) {
167
                continue;
168
            }
169
170
            $file = basename($val) . (is_dir($val) ? '/' : null);
171
            $path = (empty($this->path) ? null : $this->path . '/') . $file;
172
            $html .= "<li><a href='?path={$path}'>{$file}</a></li>\n";
173
        }
174
        $html .= "</ul>\n";
175
176
        return $html;
177
    }
178
179
180
181
    /**
182
   * Get the details such as encoding and line endings from the file.
183
   */
184
    public function detectFileDetails()
185
    {
186
187
        $this->encoding = null;
0 ignored issues
show
Bug introduced by
The property encoding does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
188
189
        // Detect character encoding
190
        if (function_exists('mb_detect_encoding')) {
191
            if ($res = mb_detect_encoding($this->content, "auto, ISO-8859-1", true)) {
0 ignored issues
show
Bug introduced by
The property content does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
192
                $this->encoding = $res;
193
            }
194
        }
195
196
        // Is it BOM?
197
        if (substr($this->content, 0, 3) == chr(0xEF) . chr(0xBB) . chr(0xBF)) {
198
            $this->encoding .= " BOM";
199
        }
200
201
        // Checking style of line-endings
202
        $this->lineendings = null;
0 ignored issues
show
Bug introduced by
The property lineendings does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
203
        if (isset($this->encoding)) {
204
            $lines = explode("\n", $this->content);
205
            $len = strlen($lines[0]);
206
207
            if (substr($lines[0], $len-1, 1) == "\r") {
208
                $this->lineendings = " Windows (CRLF) ";
209
            } else {
210
                $this->lineendings = " Unix (LF) ";
211
            }
212
        }
213
214
    }
215
216
217
218
    /**
219
   * Remove passwords from known files from all files starting with config*.
220
   */
221
    public function filterPasswords()
222
    {
223
224
        $pattern = [
225
            '/(\'|")(DB_PASSWORD|DB_USER)(.+)/',
226
            '/\$(password|passwd|pwd|pw|user|username)(\s*=\s*)(\'|")(.+)/i',
227
            //'/(\'|")(password|passwd|pwd|pw)(\'|")\s*=>\s*(.+)/i',
228
            '/(\'|")(password|passwd|pwd|pw|user|username)(\'|")(\s*=>\s*)(\'|")(.+)([\'|"].*)/i',
229
            '/(\[[\'|"])(password|passwd|pwd|pw|user|username)([\'|"]\])(\s*=\s*)(\'|")(.+)([\'|"].*)/i',
230
        ];
231
232
233
        $message = "Intentionally removed by CSource";
234
        $replace = [
235
            '\1\2\1,  "' . $message . '");',
236
            '$\1\2\3' . $message . '\3;',
237
            '\1\2\3\4\5' . $message . '\7',
238
            '\1\2\3\4\5' . $message . '\7',
239
        ];
240
241
        $this->content = preg_replace($pattern, $replace, $this->content);
242
    }
243
244
245
246
    /**
247
     * Get the content of the file and format it.
248
     *
249
     * @SuppressWarnings(PHPMD.ExitExpression)
250
     */
251
    public function getFileContent()
252
    {
253
254
        if (!isset($this->file)) {
255
            return;
256
        }
257
258
        $this->content = file_get_contents($this->realPath);
259
        $this->detectFileDetails();
260
        $this->filterPasswords();
261
262
        // Display svg-image or enable link to display svg-image.
263
        $linkToDisplaySvg = "";
264
        if ($this->extension == 'svg') {
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
265
            if (isset($_GET['displaysvg'])) {
266
                header("Content-type: image/svg+xml");
267
                echo $this->content;
268
                exit;
269
            } else {
270
                $linkToDisplaySvg = "<a href='{$_SERVER['REQUEST_URI']}&displaysvg'>Display as SVG</a>";
271
            }
272
        }
273
274
        // Display image if a valid image file
275
        if (in_array($this->extension, $this->validImageExtensions)) {
0 ignored issues
show
Bug introduced by
The property extension does not seem to exist. Did you mean validImageExtensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
276
277
            $baseDir = !empty($this->options['base_dir'])
278
            ? rtrim($this->options['base_dir'], '/') . '/'
279
            : null;
280
            $this->content = "<div style='overflow:auto;'><img src='{$baseDir}{$this->path}/{$this->file}' alt='[image not found]'></div>";
281
        } else {
282
            // Display file content and format for a syntax
283
            $this->content = str_replace('\t', $this->spaces, $this->content);
284
            $this->content = highlight_string($this->content, true);
285
            $i=0;
286
            $rownums = "";
287
            $text = "";
288
            $content = explode('<br />', $this->content);
289
290
            foreach ($content as $row) {
291
                $i++;
292
                $rownums .= "<code><a id='L{$i}' href='#L{$i}'>{$i}</a></code><br />";
293
                $text .= $row . '<br />';
294
            }
295
296
            $this->content = <<< EOD
297
<div class='src-container'>
298
<div class='src-header'><code>{$i} lines {$this->encoding} {$this->lineendings} {$linkToDisplaySvg}</code></div>
299
<div class='src-rows'>{$rownums}</div>
300
<div class='src-code'>{$text}</div>
301
</div>
302
EOD;
303
        }
304
305
        return "<h3 id='file'><code><a href='#file'>{$this->file}</a></code></h3>{$this->content}";
306
    }
307
}
308