Completed
Pull Request — remoteapiGetversions (#1573)
by Gerrit
06:07 queued 01:35
created

infoutils.php ➔ check()   F

Complexity

Conditions 37
Paths > 20000

Size

Total Lines 157
Code Lines 103

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 37
eloc 103
nc 74649600
nop 0
dl 0
loc 157
rs 2

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
 * 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_INC')) die('meh.');
9
if(!defined('DOKU_MESSAGEURL')) define('DOKU_MESSAGEURL','http://update.dokuwiki.org/check/');
10
11
/**
12
 * Check for new messages from upstream
13
 *
14
 * @author Andreas Gohr <[email protected]>
15
 */
16
function checkUpdateMessages(){
17
    global $conf;
18
    global $INFO;
19
    global $updateVersion;
20
    if(!$conf['updatecheck']) return;
21
    if($conf['useacl'] && !$INFO['ismanager']) return;
22
23
    $cf = getCacheName($updateVersion, '.updmsg');
24
    $lm = @filemtime($cf);
25
26
    // check if new messages needs to be fetched
27
    if($lm < time()-(60*60*24) || $lm < @filemtime(DOKU_INC.DOKU_SCRIPT)){
28
        @touch($cf);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
29
        dbglog("checkUpdateMessages(): downloading messages to ".$cf);
30
        $http = new DokuHTTPClient();
31
        $http->timeout = 12;
0 ignored issues
show
Bug introduced by
The property timeout cannot be accessed from this context as it is declared private in class HTTPClient.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
32
        $resp = $http->get(DOKU_MESSAGEURL.$updateVersion);
33
        if(is_string($resp) && ($resp == "" || substr(trim($resp), -1) == '%')) {
34
            // basic sanity check that this is either an empty string response (ie "no messages")
35
            // or it looks like one of our messages, not WiFi login or other interposed response
36
            io_saveFile($cf,$resp);
37
        } else {
38
            dbglog("checkUpdateMessages(): unexpected HTTP response received");
39
        }
40
    }else{
41
        dbglog("checkUpdateMessages(): messages up to date");
42
    }
43
44
    $data = io_readFile($cf);
45
    // show messages through the usual message mechanism
46
    $msgs = explode("\n%\n",$data);
47
    foreach($msgs as $msg){
48
        if($msg) msg($msg,2);
49
    }
50
}
51
52
53
/**
54
 * Return DokuWiki's version (split up in date and type)
55
 *
56
 * @author Andreas Gohr <[email protected]>
57
 */
58
function getVersionData(){
59
    $version = array();
60
    //import version string
61
    if(file_exists(DOKU_INC.'VERSION')){
62
        //official release
63
        $version['date'] = trim(io_readfile(DOKU_INC.'VERSION'));
64
        $version['type'] = 'Release';
65
    }elseif(is_dir(DOKU_INC.'.git')){
66
        $version['type'] = 'Git';
67
        $version['date'] = 'unknown';
68
69
        $inventory = DOKU_INC.'.git/logs/HEAD';
70
        if(is_file($inventory)){
71
            $sz   = filesize($inventory);
72
            $seek = max(0,$sz-2000); // read from back of the file
73
            $fh   = fopen($inventory,'rb');
74
            fseek($fh,$seek);
75
            $chunk = fread($fh,2000);
76
            fclose($fh);
77
            $chunk = trim($chunk);
78
            $chunk = @array_pop(explode("\n",$chunk));   //last log line
0 ignored issues
show
Bug introduced by
explode(' ', $chunk) cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
79
            $chunk = @array_shift(explode("\t",$chunk)); //strip commit msg
0 ignored issues
show
Bug introduced by
explode(' ', $chunk) cannot be passed to array_shift() as the parameter $array expects a reference.
Loading history...
80
            $chunk = explode(" ",$chunk);
81
            array_pop($chunk); //strip timezone
82
            $date = date('Y-m-d',array_pop($chunk));
83
            if($date) $version['date'] = $date;
84
        }
85
    }else{
86
        global $updateVersion;
87
        $version['date'] = 'update version '.$updateVersion;
88
        $version['type'] = 'snapshot?';
89
    }
90
    return $version;
91
}
92
93
/**
94
 * Return DokuWiki's version (as a string)
95
 *
96
 * @author Anika Henke <[email protected]>
97
 */
98
function getVersion(){
99
    $version = getVersionData();
100
    return $version['type'].' '.$version['date'];
101
}
102
103
/**
104
 * Run a few sanity checks
105
 *
106
 * @author Andreas Gohr <[email protected]>
107
 */
108
function check(){
109
    global $conf;
110
    global $INFO;
111
    /* @var Input $INPUT */
112
    global $INPUT;
113
114
    if ($INFO['isadmin'] || $INFO['ismanager']){
115
        msg('DokuWiki version: '.getVersion(),1);
116
117
        if(version_compare(phpversion(),'5.3.3','<')){
118
            msg('Your PHP version is too old ('.phpversion().' vs. 5.3.3+ needed)',-1);
119
        }else{
120
            msg('PHP version '.phpversion(),1);
121
        }
122
    } else {
123
        if(version_compare(phpversion(),'5.3.3','<')){
124
            msg('Your PHP version is too old',-1);
125
        }
126
    }
127
128
    $mem = (int) php_to_byte(ini_get('memory_limit'));
129
    if($mem){
130
        if($mem < 16777216){
131
            msg('PHP is limited to less than 16MB RAM ('.$mem.' bytes). Increase memory_limit in php.ini',-1);
132
        }elseif($mem < 20971520){
133
            msg('PHP is limited to less than 20MB RAM ('.$mem.' bytes), you might encounter problems with bigger pages. Increase memory_limit in php.ini',-1);
134
        }elseif($mem < 33554432){
135
            msg('PHP is limited to less than 32MB RAM ('.$mem.' bytes), but that should be enough in most cases. If not, increase memory_limit in php.ini',0);
136
        }else{
137
            msg('More than 32MB RAM ('.$mem.' bytes) available.',1);
138
        }
139
    }
140
141
    if(is_writable($conf['changelog'])){
142
        msg('Changelog is writable',1);
143
    }else{
144
        if (file_exists($conf['changelog'])) {
145
            msg('Changelog is not writable',-1);
146
        }
147
    }
148
149
    if (isset($conf['changelog_old']) && file_exists($conf['changelog_old'])) {
150
        msg('Old changelog exists', 0);
151
    }
152
153
    if (file_exists($conf['changelog'].'_failed')) {
154
        msg('Importing old changelog failed', -1);
155
    } else if (file_exists($conf['changelog'].'_importing')) {
156
        msg('Importing old changelog now.', 0);
157
    } else if (file_exists($conf['changelog'].'_import_ok')) {
158
        msg('Old changelog imported', 1);
159
        if (!plugin_isdisabled('importoldchangelog')) {
160
            msg('Importoldchangelog plugin not disabled after import', -1);
161
        }
162
    }
163
164
    if(is_writable(DOKU_CONF)){
165
        msg('conf directory is writable',1);
166
    }else{
167
        msg('conf directory is not writable',-1);
168
    }
169
170
    if($conf['authtype'] == 'plain'){
171
        global $config_cascade;
172
        if(is_writable($config_cascade['plainauth.users']['default'])){
173
            msg('conf/users.auth.php is writable',1);
174
        }else{
175
            msg('conf/users.auth.php is not writable',0);
176
        }
177
    }
178
179
    if(function_exists('mb_strpos')){
180
        if(defined('UTF8_NOMBSTRING')){
181
            msg('mb_string extension is available but will not be used',0);
182
        }else{
183
            msg('mb_string extension is available and will be used',1);
184
            if(ini_get('mbstring.func_overload') != 0){
185
                msg('mb_string function overloading is enabled, this will cause problems and should be disabled',-1);
186
            }
187
        }
188
    }else{
189
        msg('mb_string extension not available - PHP only replacements will be used',0);
190
    }
191
192
    if (!UTF8_PREGSUPPORT) {
193
        msg('PHP is missing UTF-8 support in Perl-Compatible Regular Expressions (PCRE)', -1);
194
    }
195
    if (!UTF8_PROPERTYSUPPORT) {
196
        msg('PHP is missing Unicode properties support in Perl-Compatible Regular Expressions (PCRE)', -1);
197
    }
198
199
    $loc = setlocale(LC_ALL, 0);
200
    if(!$loc){
201
        msg('No valid locale is set for your PHP setup. You should fix this',-1);
202
    }elseif(stripos($loc,'utf') === false){
203
        msg('Your locale <code>'.hsc($loc).'</code> seems not to be a UTF-8 locale, you should fix this if you encounter problems.',0);
204
    }else{
205
        msg('Valid locale '.hsc($loc).' found.', 1);
206
    }
207
208
    if($conf['allowdebug']){
209
        msg('Debugging support is enabled. If you don\'t need it you should set $conf[\'allowdebug\'] = 0',-1);
210
    }else{
211
        msg('Debugging support is disabled',1);
212
    }
213
214
    if($INFO['userinfo']['name']){
215
        msg('You are currently logged in as '.$INPUT->server->str('REMOTE_USER').' ('.$INFO['userinfo']['name'].')',0);
216
        msg('You are part of the groups '.join($INFO['userinfo']['grps'],', '),0);
217
    }else{
218
        msg('You are currently not logged in',0);
219
    }
220
221
    msg('Your current permission for this page is '.$INFO['perm'],0);
222
223
    if(is_writable($INFO['filepath'])){
224
        msg('The current page is writable by the webserver',0);
225
    }else{
226
        msg('The current page is not writable by the webserver',0);
227
    }
228
229
    if($INFO['writable']){
230
        msg('The current page is writable by you',0);
231
    }else{
232
        msg('The current page is not writable by you',0);
233
    }
234
235
    // Check for corrupted search index
236
    $lengths = idx_listIndexLengths();
237
    $index_corrupted = false;
238
    foreach ($lengths as $length) {
239
        if (count(idx_getIndex('w', $length)) != count(idx_getIndex('i', $length))) {
240
            $index_corrupted = true;
241
            break;
242
        }
243
    }
244
245
    foreach (idx_getIndex('metadata', '') as $index) {
246
        if (count(idx_getIndex($index.'_w', '')) != count(idx_getIndex($index.'_i', ''))) {
247
            $index_corrupted = true;
248
            break;
249
        }
250
    }
251
252
    if ($index_corrupted)
253
        msg('The search index is corrupted. It might produce wrong results and most
254
                probably needs to be rebuilt. See
255
                <a href="http://www.dokuwiki.org/faq:searchindex">faq:searchindex</a>
256
                for ways to rebuild the search index.', -1);
257
    elseif (!empty($lengths))
258
        msg('The search index seems to be working', 1);
259
    else
260
        msg('The search index is empty. See
261
                <a href="http://www.dokuwiki.org/faq:searchindex">faq:searchindex</a>
262
                for help on how to fix the search index. If the default indexer
263
                isn\'t used or the wiki is actually empty this is normal.');
264
}
265
266
/**
267
 * print a message
268
 *
269
 * If HTTP headers were not sent yet the message is added
270
 * to the global message array else it's printed directly
271
 * using html_msgarea()
272
 *
273
 *
274
 * Levels can be:
275
 *
276
 * -1 error
277
 *  0 info
278
 *  1 success
279
 *
280
 * @author Andreas Gohr <[email protected]>
281
 * @see    html_msgarea
282
 */
283
284
define('MSG_PUBLIC', 0);
285
define('MSG_USERS_ONLY', 1);
286
define('MSG_MANAGERS_ONLY',2);
287
define('MSG_ADMINS_ONLY',4);
288
289
/**
290
 * Display a message to the user
291
 *
292
 * @param string $message
293
 * @param int    $lvl   -1 = error, 0 = info, 1 = success, 2 = notify
294
 * @param string $line  line number
295
 * @param string $file  file number
296
 * @param int    $allow who's allowed to see the message, see MSG_* constants
297
 */
298
function msg($message,$lvl=0,$line='',$file='',$allow=MSG_PUBLIC){
299
    global $MSG, $MSG_shown;
300
    $errors = array();
301
    $errors[-1] = 'error';
302
    $errors[0]  = 'info';
303
    $errors[1]  = 'success';
304
    $errors[2]  = 'notify';
305
306
    if($line || $file) $message.=' ['.utf8_basename($file).':'.$line.']';
307
308
    if(!isset($MSG)) $MSG = array();
309
    $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message, 'allow' => $allow);
310
    if(isset($MSG_shown) || headers_sent()){
311
        if(function_exists('html_msgarea')){
312
            html_msgarea();
313
        }else{
314
            print "ERROR($lvl) $message";
315
        }
316
        unset($GLOBALS['MSG']);
317
    }
318
}
319
/**
320
 * Determine whether the current user is allowed to view the message
321
 * in the $msg data structure
322
 *
323
 * @param  $msg   array    dokuwiki msg structure
324
 *                         msg   => string, the message
325
 *                         lvl   => int, level of the message (see msg() function)
326
 *                         allow => int, flag used to determine who is allowed to see the message
327
 *                                       see MSG_* constants
328
 * @return bool
329
 */
330
function info_msg_allowed($msg){
331
    global $INFO, $auth;
332
333
    // is the message public? - everyone and anyone can see it
334
    if (empty($msg['allow']) || ($msg['allow'] == MSG_PUBLIC)) return true;
335
336
    // restricted msg, but no authentication
337
    if (empty($auth)) return false;
338
339
    switch ($msg['allow']){
340
        case MSG_USERS_ONLY:
341
            return !empty($INFO['userinfo']);
342
343
        case MSG_MANAGERS_ONLY:
344
            return $INFO['ismanager'];
345
346
        case MSG_ADMINS_ONLY:
347
            return $INFO['isadmin'];
348
349
        default:
350
            trigger_error('invalid msg allow restriction.  msg="'.$msg['msg'].'" allow='.$msg['allow'].'"', E_USER_WARNING);
351
            return $INFO['isadmin'];
352
    }
353
354
    return false;
0 ignored issues
show
Unused Code introduced by
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
355
}
356
357
/**
358
 * print debug messages
359
 *
360
 * little function to print the content of a var
361
 *
362
 * @author Andreas Gohr <[email protected]>
363
 */
364
function dbg($msg,$hidden=false){
365
    if($hidden){
366
        echo "<!--\n";
367
        print_r($msg);
368
        echo "\n-->";
369
    }else{
370
        echo '<pre class="dbg">';
371
        echo hsc(print_r($msg,true));
372
        echo '</pre>';
373
    }
374
}
375
376
/**
377
 * Print info to a log file
378
 *
379
 * @author Andreas Gohr <[email protected]>
380
 */
381
function dbglog($msg,$header=''){
382
    global $conf;
383
    /* @var Input $INPUT */
384
    global $INPUT;
385
386
    // The debug log isn't automatically cleaned thus only write it when
387
    // debugging has been enabled by the user.
388
    if($conf['allowdebug'] !== 1) return;
389
    if(is_object($msg) || is_array($msg)){
390
        $msg = print_r($msg,true);
391
    }
392
393
    if($header) $msg = "$header\n$msg";
394
395
    $file = $conf['cachedir'].'/debug.log';
396
    $fh = fopen($file,'a');
397
    if($fh){
398
        fwrite($fh,date('H:i:s ').$INPUT->server->str('REMOTE_ADDR').': '.$msg."\n");
399
        fclose($fh);
400
    }
401
}
402
403
/**
404
 * Log accesses to deprecated fucntions to the debug log
405
 *
406
 * @param string $alternative The function or method that should be used instead
407
 */
408
function dbg_deprecated($alternative = '') {
409
    global $conf;
410
    if(!$conf['allowdebug']) return;
411
412
    $backtrace = debug_backtrace();
413
    array_shift($backtrace);
414
    $self = array_shift($backtrace);
415
    $call = array_shift($backtrace);
416
417
    $called = trim($self['class'].'::'.$self['function'].'()', ':');
418
    $caller = trim($call['class'].'::'.$call['function'].'()', ':');
419
420
    $msg = $called.' is deprecated. It was called from ';
421
    $msg .= $caller.' in '.$call['file'].':'.$call['line'];
422
    if($alternative) {
423
        $msg .= ' '.$alternative.' should be used instead!';
424
    }
425
426
    dbglog($msg);
427
}
428
429
/**
430
 * Print a reversed, prettyprinted backtrace
431
 *
432
 * @author Gary Owen <[email protected]>
433
 */
434
function dbg_backtrace(){
435
    // Get backtrace
436
    $backtrace = debug_backtrace();
437
438
    // Unset call to debug_print_backtrace
439
    array_shift($backtrace);
440
441
    // Iterate backtrace
442
    $calls = array();
443
    $depth = count($backtrace) - 1;
444
    foreach ($backtrace as $i => $call) {
445
        $location = $call['file'] . ':' . $call['line'];
446
        $function = (isset($call['class'])) ?
447
            $call['class'] . $call['type'] . $call['function'] : $call['function'];
448
449
        $params = array();
450
        if (isset($call['args'])){
451
            foreach($call['args'] as $arg){
452
                if(is_object($arg)){
453
                    $params[] = '[Object '.get_class($arg).']';
454
                }elseif(is_array($arg)){
455
                    $params[] = '[Array]';
456
                }elseif(is_null($arg)){
457
                    $params[] = '[NULL]';
458
                }else{
459
                    $params[] = (string) '"'.$arg.'"';
460
                }
461
            }
462
        }
463
        $params = implode(', ',$params);
464
465
        $calls[$depth - $i] = sprintf('%s(%s) called at %s',
466
                $function,
467
                str_replace("\n", '\n', $params),
468
                $location);
469
    }
470
    ksort($calls);
471
472
    return implode("\n", $calls);
473
}
474
475
/**
476
 * Remove all data from an array where the key seems to point to sensitive data
477
 *
478
 * This is used to remove passwords, mail addresses and similar data from the
479
 * debug output
480
 *
481
 * @author Andreas Gohr <[email protected]>
482
 */
483
function debug_guard(&$data){
484
    foreach($data as $key => $value){
485
        if(preg_match('/(notify|pass|auth|secret|ftp|userinfo|token|buid|mail|proxy)/i',$key)){
486
            $data[$key] = '***';
487
            continue;
488
        }
489
        if(is_array($value)) debug_guard($data[$key]);
490
    }
491
}
492