Issues (1626)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

phpsysinfo/includes/class.CommonFunctions.inc.php (39 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * common Functions class
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PSI
9
 * @author    Michael Cramer <[email protected]>
10
 * @copyright 2009 phpSysInfo
11
 * @license   http://opensource.org/licenses/gpl-2.0.php GNU General Public License
12
 * @version   SVN: $Id: class.CommonFunctions.inc.php 699 2012-09-15 11:57:13Z namiltd $
13
 * @link      http://phpsysinfo.sourceforge.net
14
 */
15
 /**
16
 * class with common functions used in all places
17
 *
18
 * @category  PHP
19
 * @package   PSI
20
 * @author    Michael Cramer <[email protected]>
21
 * @copyright 2009 phpSysInfo
22
 * @license   http://opensource.org/licenses/gpl-2.0.php GNU General Public License
23
 * @version   Release: 3.0
24
 * @link      http://phpsysinfo.sourceforge.net
25
 */
26
class CommonFunctions
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
27
{
28
    private static function _parse_log_file($string)
29
    {
30
        if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && ((substr(PSI_LOG, 0, 1)=="-") || (substr(PSI_LOG, 0, 1)=="+"))) {
31
            $log_file = substr(PSI_LOG, 1);
32
            if (file_exists($log_file)) {
33
                $contents = @file_get_contents($log_file);
34 View Code Duplication
                if ($contents && preg_match("/^\-\-\-[^-\r\n]+\-\-\- ".preg_quote($string, '/')."\r?\n/m", $contents, $matches, PREG_OFFSET_CAPTURE)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
35
                    $findIndex = $matches[0][1];
36
                    if (preg_match("/\r?\n/m", $contents, $matches, PREG_OFFSET_CAPTURE, $findIndex)) {
37
                        $startIndex = $matches[0][1]+1;
38
                        if (preg_match("/^\-\-\-[^-\r\n]+\-\-\- /m", $contents, $matches, PREG_OFFSET_CAPTURE, $startIndex)) {
39
                            $stopIndex = $matches[0][1];
40
41
                            return substr($contents, $startIndex, $stopIndex-$startIndex);
42
                        } else {
43
                            return substr($contents, $startIndex);
44
                        }
45
                    }
46
                }
47
            }
48
        }
49
50
        return false;
51
    }
52
53
    /**
54
     * Find a system program, do also path checking when not running on WINNT
55
     * on WINNT we simply return the name with the exe extension to the program name
56
     *
57
     * @param string $strProgram name of the program
58
     *
59
     * @return string complete path and name of the program
0 ignored issues
show
Should the return type not be null|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...
60
     */
61
    private static function _findProgram($strProgram)
62
    {
63
        $path_parts = pathinfo($strProgram);
64
        if (empty($path_parts['basename'])) {
65
            return;
66
        }
67
        $arrPath = array();
68
        if ((PSI_OS == 'WINNT') && empty($path_parts['extension'])) {
69
            $strProgram .= '.exe';
70
            $path_parts = pathinfo($strProgram);
71
        }
72
        if (empty($path_parts['dirname']) || ($path_parts['dirname'] == '.')) {
73 View Code Duplication
            if (PSI_OS == 'WINNT') {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
                $arrPath = preg_split('/;/', getenv("Path"), -1, PREG_SPLIT_NO_EMPTY);
75
            } else {
76
                $arrPath = preg_split('/:/', getenv("PATH"), -1, PREG_SPLIT_NO_EMPTY);
77
            }
78
            if (defined('PSI_ADD_PATHS') && is_string(PSI_ADD_PATHS)) {
79
                if (preg_match(ARRAY_EXP, PSI_ADD_PATHS)) {
80
                    $arrPath = array_merge(eval(PSI_ADD_PATHS), $arrPath); // In this order so $addpaths is before $arrPath when looking for a program
0 ignored issues
show
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
81
                } else {
82
                    $arrPath = array_merge(array(PSI_ADD_PATHS), $arrPath); // In this order so $addpaths is before $arrPath when looking for a program
83
                }
84
            }
85
        } else {
86
            array_push($arrPath, $path_parts['dirname']);
87
            $strProgram = $path_parts['basename'];
88
        }
89
90
        //add some default paths if we still have no paths here
91
        if (empty($arrPath) && PSI_OS != 'WINNT') {
92
            if (PSI_OS == 'Android') {
93
                array_push($arrPath, '/system/bin');
94
            } else {
95
                array_push($arrPath, '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin', '/usr/local/sbin');
96
            }
97
        }
98
99
        $exceptPath = "";
100
        if ((PSI_OS == 'WINNT') && (($windir = getenv("WinDir")) !== false)) {
101
            $windir = strtolower($windir);
102
            foreach ($arrPath as $strPath) {
103
                if ((strtolower($strPath) == $windir."\\system32") && is_dir($windir."\\SysWOW64")) {
104
                    $exceptPath = $windir."\\sysnative";
105
                    array_push($arrPath, $exceptPath);
106
                    break;
107
                }
108
            }
109
        } elseif (PSI_OS == 'Android') {
110
            $exceptPath = '/system/bin';
111
        }
112
113
        // If open_basedir defined, fill the $open_basedir array with authorized paths,. (Not tested when no open_basedir restriction)
114 View Code Duplication
        if ((bool) ini_get('open_basedir')) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
            if (PSI_OS == 'WINNT') {
116
                $open_basedir = preg_split('/;/', ini_get('open_basedir'), -1, PREG_SPLIT_NO_EMPTY);
117
            } else {
118
                $open_basedir = preg_split('/:/', ini_get('open_basedir'), -1, PREG_SPLIT_NO_EMPTY);
119
            }
120
        }
121
        foreach ($arrPath as $strPath) {
122
            // Path with trailing slash
123 View Code Duplication
            if (PSI_OS == 'WINNT') {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
                $strPathS = rtrim($strPath, "\\")."\\";
125
            } else {
126
                $strPathS = rtrim($strPath, "/")."/";
127
            }
128
            // To avoid "open_basedir restriction in effect" error when testing paths if restriction is enabled
129
            if (isset($open_basedir)) {
130
                $inBaseDir = false;
131
                if (PSI_OS == 'WINNT') {
132 View Code Duplication
                    foreach ($open_basedir as $openbasedir) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
                        if (substr($openbasedir, -1)=="\\") {
134
                            $str_Path = $strPathS;
135
                        } else {
136
                            $str_Path = $strPath;
137
                        }
138
                        if (stripos($str_Path, $openbasedir) === 0) {
139
                            $inBaseDir = true;
140
                            break;
141
                        }
142
                    }
143
                } else {
144 View Code Duplication
                    foreach ($open_basedir as $openbasedir) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
                        if (substr($openbasedir, -1)=="/") {
146
                            $str_Path = $strPathS;
147
                        } else {
148
                            $str_Path = $strPath;
149
                        }
150
                        if (strpos($str_Path, $openbasedir) === 0) {
151
                            $inBaseDir = true;
152
                            break;
153
                        }
154
                    }
155
                }
156
                if ($inBaseDir == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
157
                    continue;
158
                }
159
            }
160
            if (($strPath !== $exceptPath) && !is_dir($strPath)) {
161
                continue;
162
            }
163 View Code Duplication
            if (PSI_OS == 'WINNT') {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
                $strProgrammpath = rtrim($strPath, "\\")."\\".$strProgram;
165
            } else {
166
                $strProgrammpath = rtrim($strPath, "/")."/".$strProgram;
167
            }
168
            if (is_executable($strProgrammpath)) {
169
                return $strProgrammpath;
170
            }
171
        }
172
    }
173
174
    /**
175
     * Execute a system program. return a trim()'d result.
176
     * does very crude pipe checking.  you need ' | ' for it to work
177
     * ie $program = CommonFunctions::executeProgram('netstat', '-anp | grep LIST');
178
     * NOT $program = CommonFunctions::executeProgram('netstat', '-anp|grep LIST');
179
     *
180
     * @param string  $strProgramname name of the program
181
     * @param string  $strArgs        arguments to the program
182
     * @param string  &$strBuffer     output of the command
183
     * @param boolean $booErrorRep    en- or disables the reporting of errors which should be logged
184
     *
185
     * @return boolean command successfull or not
186
     */
187
    public static function executeProgram($strProgramname, $strArgs, &$strBuffer, $booErrorRep = true)
0 ignored issues
show
The parameter $strArgs is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $booErrorRep is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
188
    {
189 View Code Duplication
        if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && ((substr(PSI_LOG, 0, 1)=="-") || (substr(PSI_LOG, 0, 1)=="+"))) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
            $out = self::_parse_log_file("Executing: ".trim($strProgramname.' '.$strArgs));
191
            if ($out == false) {
0 ignored issues
show
It seems like you are loosely comparing $out of type string|false against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
192
                if (substr(PSI_LOG, 0, 1)=="-") {
193
                    $strBuffer = '';
194
195
                    return false;
196
                }
197
            } else {
198
                $strBuffer = $out;
199
200
                return true;
201
            }
202
        }
203
204
        $strBuffer = '';
205
        $strError = '';
206
        $pipes = array();
207
        $strProgram = self::_findProgram($strProgramname);
208
        $error = PSI_Error::singleton();
0 ignored issues
show
Are you sure the assignment to $error is correct as \PSI_Error::singleton() (which targets PSI_Error::singleton()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
209
        if (!$strProgram) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $strProgram of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
210
            if ($booErrorRep) {
211
                $error->addError('find_program('.$strProgramname.')', 'program not found on the machine');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
212
            }
213
214
            return false;
215
        }
216
        // see if we've gotten a |, if we have we need to do path checking on the cmd
217
        if ($strArgs) {
218
            $arrArgs = preg_split('/ /', $strArgs, -1, PREG_SPLIT_NO_EMPTY);
219
            for ($i = 0, $cnt_args = count($arrArgs); $i < $cnt_args; $i++) {
220
                if ($arrArgs[$i] == '|') {
221
                    $strCmd = $arrArgs[$i + 1];
222
                    $strNewcmd = self::_findProgram($strCmd);
223
                    $strArgs = preg_replace("/\| ".$strCmd.'/', '| "'.$strNewcmd.'"', $strArgs);
224
                }
225
            }
226
        }
227
        $descriptorspec = array(0=>array("pipe", "r"), 1=>array("pipe", "w"), 2=>array("pipe", "w"));
228
        if (defined("PSI_MODE_POPEN") && PSI_MODE_POPEN === true) {
229
            if (PSI_OS == 'WINNT') {
230
                $process = $pipes[1] = popen('"'.$strProgram.'" '.$strArgs." 2>nul", "r");
231
            } else {
232
                $process = $pipes[1] = popen('"'.$strProgram.'" '.$strArgs." 2>/dev/null", "r");
233
            }
234
        } else {
235
            $process = proc_open('"'.$strProgram.'" '.$strArgs, $descriptorspec, $pipes);
236
        }
237
        if (is_resource($process)) {
238
            self::_timeoutfgets($pipes, $strBuffer, $strError);
239
            if (defined("PSI_MODE_POPEN") && PSI_MODE_POPEN === true) {
240
                $return_value = pclose($pipes[1]);
241
            } else {
242
                fclose($pipes[0]);
243
                fclose($pipes[1]);
244
                fclose($pipes[2]);
245
                // It is important that you close any pipes before calling
246
                // proc_close in order to avoid a deadlock
247
                $return_value = proc_close($process);
248
            }
249
        } else {
250
            if ($booErrorRep) {
251
                $error->addError($strProgram, "\nOpen process error");
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
252
            }
253
254
            return false;
255
        }
256
        $strError = trim($strError);
257
        $strBuffer = trim($strBuffer);
258
        if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && (substr(PSI_LOG, 0, 1)!="-") && (substr(PSI_LOG, 0, 1)!="+")) {
259
            error_log("---".gmdate('r T')."--- Executing: ".trim($strProgramname.' '.$strArgs)."\n".$strBuffer."\n", 3, PSI_LOG);
260
        }
261
        if (! empty($strError)) {
262
            if ($booErrorRep) {
263
                $error->addError($strProgram, $strError."\nReturn value: ".$return_value);
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
264
            }
265
266
            return $return_value == 0;
267
        }
268
269
        return true;
270
    }
271
272
    /**
273
     * read a file and return the content as a string
274
     *
275
     * @param string  $strFileName name of the file which should be read
276
     * @param string  &$strRet     content of the file (reference)
277
     * @param integer $intLines    control how many lines should be read
278
     * @param integer $intBytes    control how many bytes of each line should be read
279
     * @param boolean $booErrorRep en- or disables the reporting of errors which should be logged
280
     *
281
     * @return boolean command successfull or not
282
     */
283
    public static function rfts($strFileName, &$strRet, $intLines = 0, $intBytes = 4096, $booErrorRep = true)
0 ignored issues
show
The parameter $intBytes is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $booErrorRep is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
284
    {
285 View Code Duplication
        if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && ((substr(PSI_LOG, 0, 1)=="-") || (substr(PSI_LOG, 0, 1)=="+"))) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
286
            $out = self::_parse_log_file("Reading: ".$strFileName);
287
            if ($out == false) {
0 ignored issues
show
It seems like you are loosely comparing $out of type string|false against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
288
                if (substr(PSI_LOG, 0, 1)=="-") {
289
                    $strRet = '';
290
291
                    return false;
292
                }
293
            } else {
294
                $strRet = $out;
295
296
                return true;
297
            }
298
        }
299
300
        $strFile = "";
301
        $intCurLine = 1;
302
        $error = PSI_Error::singleton();
0 ignored issues
show
Are you sure the assignment to $error is correct as \PSI_Error::singleton() (which targets PSI_Error::singleton()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
303
        if (file_exists($strFileName)) {
304
            if (is_readable($strFileName)) {
305
                if ($fd = fopen($strFileName, 'r')) {
306
                    while (!feof($fd)) {
307
                        $strFile .= fgets($fd, $intBytes);
308
                        if ($intLines <= $intCurLine && $intLines != 0) {
309
                            break;
310
                        } else {
311
                            $intCurLine++;
312
                        }
313
                    }
314
                    fclose($fd);
315
                    $strRet = $strFile;
316
                    if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && (substr(PSI_LOG, 0, 1)!="-") && (substr(PSI_LOG, 0, 1)!="+")) {
317
                        if ((strlen($strRet)>0)&&(substr($strRet, -1)!="\n")) {
318
                            error_log("---".gmdate('r T')."--- Reading: ".$strFileName."\n".$strRet."\n", 3, PSI_LOG);
319
                        } else {
320
                            error_log("---".gmdate('r T')."--- Reading: ".$strFileName."\n".$strRet, 3, PSI_LOG);
321
                        }
322
                    }
323
                } else {
324
                    if ($booErrorRep) {
325
                        $error->addError('fopen('.$strFileName.')', 'file can not read by phpsysinfo');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
326
                    }
327
328
                    return false;
329
                }
330
            } else {
331
                if ($booErrorRep) {
332
                    $error->addError('fopen('.$strFileName.')', 'file permission error');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
333
                }
334
335
                return false;
336
            }
337
        } else {
338
            if ($booErrorRep) {
339
                $error->addError('file_exists('.$strFileName.')', 'the file does not exist on your machine');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
340
            }
341
342
            return false;
343
        }
344
345
        return true;
346
    }
347
348
    /**
349
     * file exists
350
     *
351
     * @param string $strFileName name of the file which should be check
352
     *
353
     * @return boolean command successfull or not
354
     */
355
    public static function fileexists($strFileName)
356
    {
357
        if (defined('PSI_LOG') && is_string(PSI_LOG) && (strlen(PSI_LOG)>0) && ((substr(PSI_LOG, 0, 1)=="-") || (substr(PSI_LOG, 0, 1)=="+"))) {
358
            $log_file = substr(PSI_LOG, 1);
359
            if (file_exists($log_file)
360
                && ($contents = @file_get_contents($log_file))
361
                && preg_match("/^\-\-\-[^-\n]+\-\-\- ".preg_quote("Reading: ".$strFileName, '/')."\n/m", $contents)) {
362
                return true;
363
            } else {
364
                if (substr(PSI_LOG, 0, 1)=="-") {
365
                    return false;
366
                }
367
            }
368
        }
369
370
        return file_exists($strFileName);
371
    }
372
373
    /**
374
     * reads a directory and return the name of the files and directorys in it
375
     *
376
     * @param string  $strPath     path of the directory which should be read
377
     * @param boolean $booErrorRep en- or disables the reporting of errors which should be logged
378
     *
379
     * @return array content of the directory excluding . and ..
380
     */
381
    public static function gdc($strPath, $booErrorRep = true)
382
    {
383
        $arrDirectoryContent = array();
384
        $error = PSI_Error::singleton();
0 ignored issues
show
Are you sure the assignment to $error is correct as \PSI_Error::singleton() (which targets PSI_Error::singleton()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
385
        if (is_dir($strPath)) {
386
            if ($handle = opendir($strPath)) {
387
                while (($strFile = readdir($handle)) !== false) {
388
                    if ($strFile != "." && $strFile != "..") {
389
                        $arrDirectoryContent[] = $strFile;
390
                    }
391
                }
392
                closedir($handle);
393
            } else {
394
                if ($booErrorRep) {
395
                    $error->addError('opendir('.$strPath.')', 'directory can not be read by phpsysinfo');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
396
                }
397
            }
398
        } else {
399
            if ($booErrorRep) {
400
                $error->addError('is_dir('.$strPath.')', 'directory does not exist on your machine');
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
401
            }
402
        }
403
404
        return $arrDirectoryContent;
405
    }
406
407
    /**
408
     * Check for needed php extensions
409
     *
410
     * We need that extensions for almost everything
411
     * This function will return a hard coded
412
     * XML string (with headers) if the SimpleXML extension isn't loaded.
413
     * Then it will terminate the script.
414
     * See bug #1787137
415
     *
416
     * @param array $arrExt additional extensions for which a check should run
417
     *
418
     * @return void
419
     */
420
    public static function checkForExtensions($arrExt = array())
421
    {
422
        if ((strcasecmp(PSI_SYSTEM_CODEPAGE, "UTF-8") == 0) || (strcasecmp(PSI_SYSTEM_CODEPAGE, "CP437") == 0))
423
            $arrReq = array('simplexml', 'pcre', 'xml', 'dom');
424
        elseif (PSI_OS == "WINNT")
425
            $arrReq = array('simplexml', 'pcre', 'xml', 'mbstring', 'dom', 'com_dotnet');
426
        else
427
            $arrReq = array('simplexml', 'pcre', 'xml', 'mbstring', 'dom');
428
        $extensions = array_merge($arrExt, $arrReq);
429
        $text = "";
430
        $error = false;
431
        $text .= "<?xml version='1.0'?>\n";
432
        $text .= "<phpsysinfo>\n";
433
        $text .= "  <Error>\n";
434
        foreach ($extensions as $extension) {
435
            if (!extension_loaded($extension)) {
436
                $text .= "    <Function>checkForExtensions</Function>\n";
437
                $text .= "    <Message>phpSysInfo requires the ".$extension." extension to php in order to work properly.</Message>\n";
438
                $error = true;
439
            }
440
        }
441
        $text .= "  </Error>\n";
442
        $text .= "</phpsysinfo>";
443
        if ($error) {
444
            header("Content-Type: text/xml\n\n");
445
            echo $text;
446
            die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method checkForExtensions() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
447
        }
448
    }
449
450
    /**
451
     * get the content of stdout/stderr with the option to set a timeout for reading
452
     *
453
     * @param array   $pipes   array of file pointers for stdin, stdout, stderr (proc_open())
454
     * @param string  &$out    target string for the output message (reference)
455
     * @param string  &$err    target string for the error message (reference)
456
     * @param integer $timeout timeout value in seconds (default value is 30)
457
     *
458
     * @return void
459
     */
460
    private static function _timeoutfgets($pipes, &$out, &$err, $timeout = 30)
461
    {
462
        $w = null;
463
        $e = null;
464
465
        if (defined("PSI_MODE_POPEN") && PSI_MODE_POPEN === true) {
466
            $pipe2 = false;
467
        } else {
468
            $pipe2 = true;
469
        }
470
        while (!(feof($pipes[1]) && (!$pipe2 || feof($pipes[2])))) {
471
            if ($pipe2) {
472
                $read = array($pipes[1], $pipes[2]);
473
            } else {
474
                $read = array($pipes[1]);
475
            }
476
477
            $n = stream_select($read, $w, $e, $timeout);
478
479
            if ($n === false) {
480
                error_log('stream_select: failed !');
481
                break;
482
            } elseif ($n === 0) {
483
                error_log('stream_select: timeout expired !');
484
                break;
485
            }
486
487
            foreach ($read as $r) {
488
                if ($r == $pipes[1]) {
489
                    $out .= fread($r, 4096);
490
                } elseif (feof($pipes[1]) && $pipe2 && ($r == $pipes[2])) {//read STDERR after STDOUT
491
                    $err .= fread($r, 4096);
492
                }
493
            }
494
        }
495
    }
496
497
    /**
498
     * function for getting a list of values in the specified context
499
     * optionally filter this list, based on the list from third parameter
500
     *
501
     * @param $wmi holds the COM object that we pull the WMI data from
502
     * @param string $strClass name of the class where the values are stored
503
     * @param array  $strValue filter out only needed values, if not set all values of the class are returned
504
     *
505
     * @return array content of the class stored in an array
506
     */
507
    public static function getWMI($wmi, $strClass, $strValue = array())
508
    {
509
        $arrData = array();
510
        if ($wmi) {
511
            $value = "";
0 ignored issues
show
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
512
            try {
513
                $objWEBM = $wmi->Get($strClass);
514
                $arrProp = $objWEBM->Properties_;
515
                $arrWEBMCol = $objWEBM->Instances_();
516
                foreach ($arrWEBMCol as $objItem) {
517
                    if (is_array($arrProp)) {
518
                        reset($arrProp);
519
                    }
520
                    $arrInstance = array();
521
                    foreach ($arrProp as $propItem) {
522
                        $value = $objItem->{$propItem->Name}; //instead exploitable eval("\$value = \$objItem->".$propItem->Name.";");
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
523
                        if (empty($strValue)) {
524 View Code Duplication
                            if (is_string($value)) $arrInstance[$propItem->Name] = trim($value);
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
525
                            else $arrInstance[$propItem->Name] = $value;
526 View Code Duplication
                        } else {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
527
                            if (in_array($propItem->Name, $strValue)) {
528
                                if (is_string($value)) $arrInstance[$propItem->Name] = trim($value);
529
                                else $arrInstance[$propItem->Name] = $value;
530
                            }
531
                        }
532
                    }
533
                    $arrData[] = $arrInstance;
534
                }
535
            } catch (Exception $e) {
536
                if (PSI_DEBUG) {
537
                    $error = PSI_Error::singleton();
0 ignored issues
show
Are you sure the assignment to $error is correct as \PSI_Error::singleton() (which targets PSI_Error::singleton()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
538
                    $error->addError($e->getCode(), $e->getMessage());
0 ignored issues
show
The method addError cannot be called on $error (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
539
                }
540
            }
541
        }
542
543
        return $arrData;
544
    }
545
546
    /**
547
     * get all configured plugins from phpsysinfo.ini (file must be included and processed before calling this function)
548
     *
549
     * @return array
550
     */
551
    public static function getPlugins()
552
    {
553
        if (defined('PSI_PLUGINS') && is_string(PSI_PLUGINS)) {
554
            if (preg_match(ARRAY_EXP, PSI_PLUGINS)) {
555
                return eval(strtolower(PSI_PLUGINS));
0 ignored issues
show
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
556
            } else {
557
                return array(strtolower(PSI_PLUGINS));
558
            }
559
        } else {
560
            return array();
561
        }
562
    }
563
}
564