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

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
454
 * @triggers INFO_DEPRECATION_LOG
455
 */
456
function dbg_deprecated($alternative = '') {
457
    \dokuwiki\Debug\DebugHelper::dbgDeprecatedFunction($alternative, 2);
458
}
459
460
/**
461
 * Print a reversed, prettyprinted backtrace
462
 *
463
 * @author Gary Owen <[email protected]>
464
 */
465
function dbg_backtrace(){
466
    // Get backtrace
467
    $backtrace = debug_backtrace();
468
469
    // Unset call to debug_print_backtrace
470
    array_shift($backtrace);
471
472
    // Iterate backtrace
473
    $calls = array();
474
    $depth = count($backtrace) - 1;
475
    foreach ($backtrace as $i => $call) {
476
        $location = $call['file'] . ':' . $call['line'];
477
        $function = (isset($call['class'])) ?
478
            $call['class'] . $call['type'] . $call['function'] : $call['function'];
479
480
        $params = array();
481
        if (isset($call['args'])){
482
            foreach($call['args'] as $arg){
483
                if(is_object($arg)){
484
                    $params[] = '[Object '.get_class($arg).']';
485
                }elseif(is_array($arg)){
486
                    $params[] = '[Array]';
487
                }elseif(is_null($arg)){
488
                    $params[] = '[NULL]';
489
                }else{
490
                    $params[] = (string) '"'.$arg.'"';
491
                }
492
            }
493
        }
494
        $params = implode(', ',$params);
495
496
        $calls[$depth - $i] = sprintf('%s(%s) called at %s',
497
                $function,
498
                str_replace("\n", '\n', $params),
499
                $location);
500
    }
501
    ksort($calls);
502
503
    return implode("\n", $calls);
504
}
505
506
/**
507
 * Remove all data from an array where the key seems to point to sensitive data
508
 *
509
 * This is used to remove passwords, mail addresses and similar data from the
510
 * debug output
511
 *
512
 * @author Andreas Gohr <[email protected]>
513
 *
514
 * @param array $data
515
 */
516
function debug_guard(&$data){
517
    foreach($data as $key => $value){
518
        if(preg_match('/(notify|pass|auth|secret|ftp|userinfo|token|buid|mail|proxy)/i',$key)){
519
            $data[$key] = '***';
520
            continue;
521
        }
522
        if(is_array($value)) debug_guard($data[$key]);
523
    }
524
}
525