Failed Conditions
Pull Request — psr2 (#2725)
by Michael
09:53 queued 06:49
created

inc/infoutils.php (1 issue)

Labels
Severity

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
 * Information and debugging functions
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Andreas Gohr <[email protected]>
7
 */
8
9
use dokuwiki\HTTP\DokuHTTPClient;
0 ignored issues
show
This use statement conflicts with another class in this namespace, DokuHTTPClient.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
10
11
if(!defined('DOKU_MESSAGEURL')){
12
    if(in_array('ssl', stream_get_transports())) {
13
        define('DOKU_MESSAGEURL','https://update.dokuwiki.org/check/');
14
    }else{
15
        define('DOKU_MESSAGEURL','http://update.dokuwiki.org/check/');
16
    }
17
}
18
19
/**
20
 * Check for new messages from upstream
21
 *
22
 * @author Andreas Gohr <[email protected]>
23
 */
24
function checkUpdateMessages(){
25
    global $conf;
26
    global $INFO;
27
    global $updateVersion;
28
    if(!$conf['updatecheck']) return;
29
    if($conf['useacl'] && !$INFO['ismanager']) return;
30
31
    $cf = getCacheName($updateVersion, '.updmsg');
32
    $lm = @filemtime($cf);
33
    $is_http = substr(DOKU_MESSAGEURL, 0, 5) != 'https';
34
35
    // check if new messages needs to be fetched
36
    if($lm < time()-(60*60*24) || $lm < @filemtime(DOKU_INC.DOKU_SCRIPT)){
37
        @touch($cf);
38
        dbglog("checkUpdateMessages(): downloading messages to ".$cf.($is_http?' (without SSL)':' (with SSL)'));
39
        $http = new DokuHTTPClient();
40
        $http->timeout = 12;
41
        $resp = $http->get(DOKU_MESSAGEURL.$updateVersion);
42
        if(is_string($resp) && ($resp == "" || substr(trim($resp), -1) == '%')) {
43
            // basic sanity check that this is either an empty string response (ie "no messages")
44
            // or it looks like one of our messages, not WiFi login or other interposed response
45
            io_saveFile($cf,$resp);
46
        } else {
47
            dbglog("checkUpdateMessages(): unexpected HTTP response received");
48
        }
49
    }else{
50
        dbglog("checkUpdateMessages(): messages up to date");
51
    }
52
53
    $data = io_readFile($cf);
54
    // show messages through the usual message mechanism
55
    $msgs = explode("\n%\n",$data);
56
    foreach($msgs as $msg){
57
        if($msg) msg($msg,2);
58
    }
59
}
60
61
62
/**
63
 * Return DokuWiki's version (split up in date and type)
64
 *
65
 * @author Andreas Gohr <[email protected]>
66
 */
67
function getVersionData(){
68
    $version = array();
69
    //import version string
70
    if(file_exists(DOKU_INC.'VERSION')){
71
        //official release
72
        $version['date'] = trim(io_readFile(DOKU_INC.'VERSION'));
73
        $version['type'] = 'Release';
74
    }elseif(is_dir(DOKU_INC.'.git')){
75
        $version['type'] = 'Git';
76
        $version['date'] = 'unknown';
77
78
        $inventory = DOKU_INC.'.git/logs/HEAD';
79
        if(is_file($inventory)){
80
            $sz   = filesize($inventory);
81
            $seek = max(0,$sz-2000); // read from back of the file
82
            $fh   = fopen($inventory,'rb');
83
            fseek($fh,$seek);
84
            $chunk = fread($fh,2000);
85
            fclose($fh);
86
            $chunk = trim($chunk);
87
            $chunk = @array_pop(explode("\n",$chunk));   //last log line
88
            $chunk = @array_shift(explode("\t",$chunk)); //strip commit msg
89
            $chunk = explode(" ",$chunk);
90
            array_pop($chunk); //strip timezone
91
            $date = date('Y-m-d',array_pop($chunk));
92
            if($date) $version['date'] = $date;
93
        }
94
    }else{
95
        global $updateVersion;
96
        $version['date'] = 'update version '.$updateVersion;
97
        $version['type'] = 'snapshot?';
98
    }
99
    return $version;
100
}
101
102
/**
103
 * Return DokuWiki's version (as a string)
104
 *
105
 * @author Anika Henke <[email protected]>
106
 */
107
function getVersion(){
108
    $version = getVersionData();
109
    return $version['type'].' '.$version['date'];
110
}
111
112
/**
113
 * Run a few sanity checks
114
 *
115
 * @author Andreas Gohr <[email protected]>
116
 */
117
function check(){
118
    global $conf;
119
    global $INFO;
120
    /* @var Input $INPUT */
121
    global $INPUT;
122
123
    if ($INFO['isadmin'] || $INFO['ismanager']){
124
        msg('DokuWiki version: '.getVersion(),1);
125
126
        if(version_compare(phpversion(),'5.6.0','<')){
127
            msg('Your PHP version is too old ('.phpversion().' vs. 5.6.0+ needed)',-1);
128
        }else{
129
            msg('PHP version '.phpversion(),1);
130
        }
131
    } else {
132
        if(version_compare(phpversion(),'5.6.0','<')){
133
            msg('Your PHP version is too old',-1);
134
        }
135
    }
136
    $limit = ini_get('memory_limit');
137
    if($limit == -1) {
138
        $mem = -1; // unlimited
139
    } else {
140
        $mem = (int) php_to_byte($limit);
141
    }
142
    if($mem){
143
        if($mem == -1) {
144
            msg('PHP memory is unlimited', 1);
145
        } else if($mem < 16777216){
146
            msg('PHP is limited to less than 16MB RAM ('.$mem.' bytes). Increase memory_limit in php.ini',-1);
147
        }else if($mem < 20971520){
148
            msg('PHP is limited to less than 20MB RAM ('.$mem.' bytes), 
149
                 you might encounter problems with bigger pages. Increase memory_limit in php.ini',-1);
150
        }else if($mem < 33554432){
151
            msg('PHP is limited to less than 32MB RAM ('.$mem.' bytes), 
152
                 but that should be enough in most cases. If not, increase memory_limit in php.ini',0);
153
        }else{
154
            msg('More than 32MB RAM ('.$mem.' bytes) available.',1);
155
        }
156
    }
157
158
    if(is_writable($conf['changelog'])){
159
        msg('Changelog is writable',1);
160
    }else{
161
        if (file_exists($conf['changelog'])) {
162
            msg('Changelog is not writable',-1);
163
        }
164
    }
165
166
    if (isset($conf['changelog_old']) && file_exists($conf['changelog_old'])) {
167
        msg('Old changelog exists', 0);
168
    }
169
170
    if (file_exists($conf['changelog'].'_failed')) {
171
        msg('Importing old changelog failed', -1);
172
    } else if (file_exists($conf['changelog'].'_importing')) {
173
        msg('Importing old changelog now.', 0);
174
    } else if (file_exists($conf['changelog'].'_import_ok')) {
175
        msg('Old changelog imported', 1);
176
        if (!plugin_isdisabled('importoldchangelog')) {
177
            msg('Importoldchangelog plugin not disabled after import', -1);
178
        }
179
    }
180
181
    if(is_writable(DOKU_CONF)){
182
        msg('conf directory is writable',1);
183
    }else{
184
        msg('conf directory is not writable',-1);
185
    }
186
187
    if($conf['authtype'] == 'plain'){
188
        global $config_cascade;
189
        if(is_writable($config_cascade['plainauth.users']['default'])){
190
            msg('conf/users.auth.php is writable',1);
191
        }else{
192
            msg('conf/users.auth.php is not writable',0);
193
        }
194
    }
195
196
    if(function_exists('mb_strpos')){
197
        if(defined('UTF8_NOMBSTRING')){
198
            msg('mb_string extension is available but will not be used',0);
199
        }else{
200
            msg('mb_string extension is available and will be used',1);
201
            if(ini_get('mbstring.func_overload') != 0){
202
                msg('mb_string function overloading is enabled, this will cause problems and should be disabled',-1);
203
            }
204
        }
205
    }else{
206
        msg('mb_string extension not available - PHP only replacements will be used',0);
207
    }
208
209
    if (!UTF8_PREGSUPPORT) {
210
        msg('PHP is missing UTF-8 support in Perl-Compatible Regular Expressions (PCRE)', -1);
211
    }
212
    if (!UTF8_PROPERTYSUPPORT) {
213
        msg('PHP is missing Unicode properties support in Perl-Compatible Regular Expressions (PCRE)', -1);
214
    }
215
216
    $loc = setlocale(LC_ALL, 0);
217
    if(!$loc){
218
        msg('No valid locale is set for your PHP setup. You should fix this',-1);
219
    }elseif(stripos($loc,'utf') === false){
220
        msg('Your locale <code>'.hsc($loc).'</code> seems not to be a UTF-8 locale,
221
             you should fix this if you encounter problems.',0);
222
    }else{
223
        msg('Valid locale '.hsc($loc).' found.', 1);
224
    }
225
226
    if($conf['allowdebug']){
227
        msg('Debugging support is enabled. If you don\'t need it you should set $conf[\'allowdebug\'] = 0',-1);
228
    }else{
229
        msg('Debugging support is disabled',1);
230
    }
231
232
    if($INFO['userinfo']['name']){
233
        msg('You are currently logged in as '.$INPUT->server->str('REMOTE_USER').' ('.$INFO['userinfo']['name'].')',0);
234
        msg('You are part of the groups '.join($INFO['userinfo']['grps'],', '),0);
235
    }else{
236
        msg('You are currently not logged in',0);
237
    }
238
239
    msg('Your current permission for this page is '.$INFO['perm'],0);
240
241
    if(is_writable($INFO['filepath'])){
242
        msg('The current page is writable by the webserver',0);
243
    }else{
244
        msg('The current page is not writable by the webserver',0);
245
    }
246
247
    if($INFO['writable']){
248
        msg('The current page is writable by you',0);
249
    }else{
250
        msg('The current page is not writable by you',0);
251
    }
252
253
    // Check for corrupted search index
254
    $lengths = idx_listIndexLengths();
255
    $index_corrupted = false;
256
    foreach ($lengths as $length) {
257
        if (count(idx_getIndex('w', $length)) != count(idx_getIndex('i', $length))) {
258
            $index_corrupted = true;
259
            break;
260
        }
261
    }
262
263
    foreach (idx_getIndex('metadata', '') as $index) {
264
        if (count(idx_getIndex($index.'_w', '')) != count(idx_getIndex($index.'_i', ''))) {
265
            $index_corrupted = true;
266
            break;
267
        }
268
    }
269
270
    if($index_corrupted) {
271
        msg(
272
            'The search index is corrupted. It might produce wrong results and most
273
                probably needs to be rebuilt. See
274
                <a href="http://www.dokuwiki.org/faq:searchindex">faq:searchindex</a>
275
                for ways to rebuild the search index.', -1
276
        );
277
    } elseif(!empty($lengths)) {
278
        msg('The search index seems to be working', 1);
279
    } else {
280
        msg(
281
            'The search index is empty. See
282
                <a href="http://www.dokuwiki.org/faq:searchindex">faq:searchindex</a>
283
                for help on how to fix the search index. If the default indexer
284
                isn\'t used or the wiki is actually empty this is normal.'
285
        );
286
    }
287
288
    // rough time check
289
    $http = new DokuHTTPClient();
290
    $http->max_redirect = 0;
291
    $http->timeout = 3;
292
    $http->sendRequest('http://www.dokuwiki.org', '', 'HEAD');
293
    $now = time();
294
    if(isset($http->resp_headers['date'])) {
295
        $time = strtotime($http->resp_headers['date']);
296
        $diff = $time - $now;
297
298
        if(abs($diff) < 4) {
299
            msg("Server time seems to be okay. Diff: {$diff}s", 1);
300
        } else {
301
            msg("Your server's clock seems to be out of sync!
302
                 Consider configuring a sync with a NTP server.  Diff: {$diff}s");
303
        }
304
    }
305
306
}
307
308
/**
309
 * print a message
310
 *
311
 * If HTTP headers were not sent yet the message is added
312
 * to the global message array else it's printed directly
313
 * using html_msgarea()
314
 *
315
 *
316
 * Levels can be:
317
 *
318
 * -1 error
319
 *  0 info
320
 *  1 success
321
 *
322
 * @author Andreas Gohr <[email protected]>
323
 * @see    html_msgarea
324
 */
325
326
define('MSG_PUBLIC', 0);
327
define('MSG_USERS_ONLY', 1);
328
define('MSG_MANAGERS_ONLY',2);
329
define('MSG_ADMINS_ONLY',4);
330
331
/**
332
 * Display a message to the user
333
 *
334
 * @param string $message
335
 * @param int    $lvl   -1 = error, 0 = info, 1 = success, 2 = notify
336
 * @param string $line  line number
337
 * @param string $file  file number
338
 * @param int    $allow who's allowed to see the message, see MSG_* constants
339
 */
340
function msg($message,$lvl=0,$line='',$file='',$allow=MSG_PUBLIC){
341
    global $MSG, $MSG_shown;
342
    $errors = array();
343
    $errors[-1] = 'error';
344
    $errors[0]  = 'info';
345
    $errors[1]  = 'success';
346
    $errors[2]  = 'notify';
347
348
    if($line || $file) $message.=' ['.utf8_basename($file).':'.$line.']';
349
350
    if(!isset($MSG)) $MSG = array();
351
    $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message, 'allow' => $allow);
352
    if(isset($MSG_shown) || headers_sent()){
353
        if(function_exists('html_msgarea')){
354
            html_msgarea();
355
        }else{
356
            print "ERROR($lvl) $message";
357
        }
358
        unset($GLOBALS['MSG']);
359
    }
360
}
361
/**
362
 * Determine whether the current user is allowed to view the message
363
 * in the $msg data structure
364
 *
365
 * @param  $msg   array    dokuwiki msg structure
366
 *                         msg   => string, the message
367
 *                         lvl   => int, level of the message (see msg() function)
368
 *                         allow => int, flag used to determine who is allowed to see the message
369
 *                                       see MSG_* constants
370
 * @return bool
371
 */
372
function info_msg_allowed($msg){
373
    global $INFO, $auth;
374
375
    // is the message public? - everyone and anyone can see it
376
    if (empty($msg['allow']) || ($msg['allow'] == MSG_PUBLIC)) return true;
377
378
    // restricted msg, but no authentication
379
    if (empty($auth)) return false;
380
381
    switch ($msg['allow']){
382
        case MSG_USERS_ONLY:
383
            return !empty($INFO['userinfo']);
384
385
        case MSG_MANAGERS_ONLY:
386
            return $INFO['ismanager'];
387
388
        case MSG_ADMINS_ONLY:
389
            return $INFO['isadmin'];
390
391
        default:
392
            trigger_error('invalid msg allow restriction.  msg="'.$msg['msg'].'" allow='.$msg['allow'].'"',
393
                          E_USER_WARNING);
394
            return $INFO['isadmin'];
395
    }
396
397
    return false;
398
}
399
400
/**
401
 * print debug messages
402
 *
403
 * little function to print the content of a var
404
 *
405
 * @author Andreas Gohr <[email protected]>
406
 *
407
 * @param string $msg
408
 * @param bool $hidden
409
 */
410
function dbg($msg,$hidden=false){
411
    if($hidden){
412
        echo "<!--\n";
413
        print_r($msg);
414
        echo "\n-->";
415
    }else{
416
        echo '<pre class="dbg">';
417
        echo hsc(print_r($msg,true));
418
        echo '</pre>';
419
    }
420
}
421
422
/**
423
 * Print info to a log file
424
 *
425
 * @author Andreas Gohr <[email protected]>
426
 *
427
 * @param string $msg
428
 * @param string $header
429
 */
430
function dbglog($msg,$header=''){
431
    global $conf;
432
    /* @var Input $INPUT */
433
    global $INPUT;
434
435
    // The debug log isn't automatically cleaned thus only write it when
436
    // debugging has been enabled by the user.
437
    if($conf['allowdebug'] !== 1) return;
438
    if(is_object($msg) || is_array($msg)){
439
        $msg = print_r($msg,true);
440
    }
441
442
    if($header) $msg = "$header\n$msg";
443
444
    $file = $conf['cachedir'].'/debug.log';
445
    $fh = fopen($file,'a');
446
    if($fh){
447
        fwrite($fh,date('H:i:s ').$INPUT->server->str('REMOTE_ADDR').': '.$msg."\n");
448
        fclose($fh);
449
    }
450
}
451
452
/**
453
 * Log accesses to deprecated fucntions to the debug log
454
 *
455
 * @param string $alternative The function or method that should be used instead
456
 * @param string|null $deprecatedThing What is deprecated if not the current method
457
 * @triggers INFO_DEPRECATION_LOG
458
 */
459
function dbg_deprecated($alternative = '') {
460
    \dokuwiki\Debug\DebugHelper::dbgDeprecatedFunction($alternative, 2);
461
}
462
463
/**
464
 * Print a reversed, prettyprinted backtrace
465
 *
466
 * @author Gary Owen <[email protected]>
467
 */
468
function dbg_backtrace(){
469
    // Get backtrace
470
    $backtrace = debug_backtrace();
471
472
    // Unset call to debug_print_backtrace
473
    array_shift($backtrace);
474
475
    // Iterate backtrace
476
    $calls = array();
477
    $depth = count($backtrace) - 1;
478
    foreach ($backtrace as $i => $call) {
479
        $location = $call['file'] . ':' . $call['line'];
480
        $function = (isset($call['class'])) ?
481
            $call['class'] . $call['type'] . $call['function'] : $call['function'];
482
483
        $params = array();
484
        if (isset($call['args'])){
485
            foreach($call['args'] as $arg){
486
                if(is_object($arg)){
487
                    $params[] = '[Object '.get_class($arg).']';
488
                }elseif(is_array($arg)){
489
                    $params[] = '[Array]';
490
                }elseif(is_null($arg)){
491
                    $params[] = '[NULL]';
492
                }else{
493
                    $params[] = (string) '"'.$arg.'"';
494
                }
495
            }
496
        }
497
        $params = implode(', ',$params);
498
499
        $calls[$depth - $i] = sprintf('%s(%s) called at %s',
500
                $function,
501
                str_replace("\n", '\n', $params),
502
                $location);
503
    }
504
    ksort($calls);
505
506
    return implode("\n", $calls);
507
}
508
509
/**
510
 * Remove all data from an array where the key seems to point to sensitive data
511
 *
512
 * This is used to remove passwords, mail addresses and similar data from the
513
 * debug output
514
 *
515
 * @author Andreas Gohr <[email protected]>
516
 *
517
 * @param array $data
518
 */
519
function debug_guard(&$data){
520
    foreach($data as $key => $value){
521
        if(preg_match('/(notify|pass|auth|secret|ftp|userinfo|token|buid|mail|proxy)/i',$key)){
522
            $data[$key] = '***';
523
            continue;
524
        }
525
        if(is_array($value)) debug_guard($data[$key]);
526
    }
527
}
528