Passed
Push — master ( 8e685f...ce48d5 )
by Kevin
13:20
created

cert_filename()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 2
rs 10
1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
// Utility functions for BOINC web pages
20
// Stuff that's not web-specific (e.g. that's used in non-web scripts)
21
// should go in util_basic.inc
22
23
24
error_reporting(E_ALL);
25
ini_set('display_errors', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

25
ini_set('display_errors', /** @scrutinizer ignore-type */ true);
Loading history...
26
ini_set('display_startup_errors', true);
27
28
require_once("../inc/util_basic.inc");
29
require_once("../project/project.inc");
30
require_once("../inc/countries.inc");
31
require_once("../inc/db.inc");
32
require_once("../inc/boinc_db.inc");
33
require_once("../inc/translation.inc");
34
require_once("../inc/profile.inc");
35
require_once("../inc/bootstrap.inc");
36
37
// parse some stuff from config (do it here for efficiency)
38
//
39
$config = get_config();
40
global $master_url;
41
$master_url = parse_config($config , "<master_url>");
42
$recaptcha_public_key = parse_config($config, "<recaptcha_public_key>");
43
$recaptcha_private_key = parse_config($config, "<recaptcha_private_key>");
44
45
// don't allow /... at the end of URL
46
47
if (array_key_exists("PATH_INFO", $_SERVER)) {
48
    die("bad URL");
49
}
50
51
// define TIMEZONE in project.inc
52
//
53
if (defined('TIMEZONE')) {
54
    date_default_timezone_set(TIMEZONE);
55
} else {
56
    date_default_timezone_set('UTC');
57
}
58
59
if (!defined('DISABLE_PROFILES')) {
60
    define('DISABLE_PROFILES', false);
61
}
62
if (!defined('DISABLE_FORUMS')) {
63
    define('DISABLE_FORUMS', false);
64
}
65
if (!defined('DISABLE_TEAMS')) {
66
    define('DISABLE_TEAMS', false);
67
}
68
if (!defined('DISABLE_BADGES')) {
69
    define('DISABLE_BADGES', false);
70
}
71
if (!defined('BADGE_HEIGHT_SMALL')) {
72
    define('BADGE_HEIGHT_SMALL', 20);
73
}
74
if (!defined('BADGE_HEIGHT_MEDIUM')) {
75
    define('BADGE_HEIGHT_MEDIUM', 24);
76
}
77
if (!defined('BADGE_HEIGHT_LARGE')) {
78
    define('BADGE_HEIGHT_LARGE', 56);
79
}
80
if (!defined('LDAP_HOST')) {
81
    define('LDAP_HOST', null);
82
}
83
if (!defined('POSTAL_CODE')) {
84
    define('POSTAL_CODE', false);
85
}
86
if (!defined('NO_COMPUTING')) {
87
    define('NO_COMPUTING', false);
88
}
89
if (!defined('NO_HOSTS')) {
90
    define('NO_HOSTS', false);
91
}
92
if (!defined('NO_STATS')) {
93
    define('NO_STATS', false);
94
}
95
if (!defined('NO_GLOBAL_PREFS')) {
96
    define('NO_GLOBAL_PREFS', false);
97
}
98
if (!defined('USER_HOME')) {
99
    define('USER_HOME', 'home.php');
100
}
101
if (!defined('POST_MAX_LINKS')) {
102
    define('POST_MAX_LINKS', 0);
103
}
104
105
// sleep this long on any login failure
106
// (slow the rate of hacker attacks)
107
//
108
define('LOGIN_FAIL_SLEEP_SEC', 5);
109
110
$caching = false;
111
    // if set, we're writing to a file rather than to client
112
$did_page_head = false;
113
114
define('KILO', 1024);
115
define('MEGA', 1024*KILO);
116
define('GIGA', 1024*MEGA);
117
118
// return true if this page is HTTPS
119
//
120
function is_https() {
121
    return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'];
122
}
123
124
function secure_url_base() {
125
    if (defined('SECURE_URL_BASE')) return SECURE_URL_BASE;
126
    return URL_BASE;
127
}
128
129
function url_base() {
130
    return is_https()?secure_url_base():URL_BASE;
131
}
132
133
function send_cookie($name, $value, $permanent, $ops=false) {
134
    global $master_url;
135
136
    // the following allows independent login for projects on the same server
137
    //
138
    $url = parse_url($master_url);
139
    $path = $url['path'];
140
    if ($ops) {
141
        $path = substr($path, 0, -1);
142
        $path .= "_ops/";
143
    }
144
    $expire = $permanent?time()+3600*24*365:0;
145
    setcookie($name, $value, $expire, $path);
146
}
147
148
function clear_cookie($name, $ops=false) {
149
    global $master_url;
150
    $url = parse_url($master_url);
151
    $path = $url['path'];
152
    if ($ops) {
153
        $path = substr($path, 0, -1);
154
        $path .= "_ops/";
155
    }
156
    setcookie($name, '', time()-3600, $path);
157
}
158
159
$g_logged_in_user = null;
160
$got_logged_in_user = false;
161
162
function get_logged_in_user($must_be_logged_in=true) {
163
    global $g_logged_in_user, $got_logged_in_user;
164
    if ($got_logged_in_user) return $g_logged_in_user;
165
166
    if (web_stopped()) return null;
167
168
    $authenticator = null;
169
    if (isset($_COOKIE['auth'])) $authenticator = $_COOKIE['auth'];
170
171
    $authenticator = BoincDb::escape_string($authenticator);
172
    if ($authenticator) {
173
        $g_logged_in_user = BoincUser::lookup("authenticator='$authenticator'");
174
    }
175
    if ($must_be_logged_in && !$g_logged_in_user) {
176
        $next_url = '';
177
        if (array_key_exists('REQUEST_URI', $_SERVER)) {
178
            $next_url = $_SERVER['REQUEST_URI'];
179
            $n = strrpos($next_url, "/");
180
            if ($n) {
181
                $next_url = substr($next_url, $n+1);
182
            }
183
        }
184
        $next_url = urlencode($next_url);
185
        Header("Location: ".url_base()."login_form.php?next_url=$next_url");
0 ignored issues
show
Coding Style introduced by
Calls to inbuilt PHP functions must be lowercase; expected "header" but found "Header"
Loading history...
186
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
187
    }
188
    $got_logged_in_user = true;
189
    return $g_logged_in_user;
190
}
191
192
function show_login_info($prefix="") {
193
    $user = get_logged_in_user(false);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $user is correct as get_logged_in_user(false) 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...
194
    if ($user) {
195
        $url_tokens = url_tokens($user->authenticator);
196
        echo "<nobr>$user->name &middot; <a href=".$prefix."logout.php?$url_tokens>".tra("log out")."</a></nobr>";
197
    } else {
198
        echo "<a href=".$prefix."login_form.php>".tra("log in")."</a>";
199
    }
200
}
201
202
$cache_control_extra="";
203
$is_login_page = false;
204
205
// Call this to start pages.
206
// Outputs some HTML boilerplate,
207
// then calls project_banner() (in html/project/project.inc)
208
// to output whatever you want at the top of your web pages.
209
//
210
// Page_head() is overridable so that projects that want to integrate BOINC
211
// with an existing web framework can more easily do so.
212
// To do so, define page_head() in the project include file.
213
//
214
if (!function_exists("page_head")){
215
function page_head(
216
    $title,
217
        // page title. Put in <title>, used as title for browser tab.
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
218
    $body_attrs=null,
219
        // <body XXXX>
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
220
        // e.g. Javascript to put focus in an input field
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
221
        // (onload="document.form.foo.focus()")
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
222
        // or to jump to a particular post (onload="jumpToUnread();")
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
223
    $is_main = false,
224
        // if set, include schedulers.txt.
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
225
        // also pass to project_banner() in case you want a different
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
226
        // header for your main page.
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
227
    $url_prefix="",
228
        // prepend this to links.
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
229
        // Use for web pages not in the top directory
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
230
    $head_extra=null
231
        // extra stuff to put in <head>. E.g.:
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
232
        // reCAPTCHA code (create_profile.php)
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
233
        // bbcode javascript (forums)
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
234
) {
235
    global $caching, $cache_control_extra, $did_page_head;
236
    global $is_login_page, $fixed_navbar;
237
238
    $did_page_head = true;
239
    $url_base = url_base();
240
241
    $rssname = "RSS 2.0";
242
    $rsslink = $url_base."rss_main.php";
243
244
    if (!$caching) {
245
        header("Content-type: text/html; charset=utf-8");
246
        header ("Expires: Mon, 26 Jul 1997 05:00:00 UTC");    // Date in the past
247
        header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " UTC"); // always modified
248
        header ("Cache-Control: $cache_control_extra no-cache, must-revalidate, post-check=0, pre-check=0");  // HTTP/1.1
249
        header ("Pragma: no-cache");                          // HTTP/1.0
250
    }
251
252
    echo '<!DOCTYPE html>
253
        <html lang="en">
254
        <head>
255
        <meta name="viewport" content="width=device-width, initial-scale=1">
256
    ';
257
    if ($head_extra) {
258
        echo "\n$head_extra\n";
259
    }
260
    if ($is_main && (!defined('NO_COMPUTING')||!NO_COMPUTING)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before logical operator; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after logical operator; 0 found
Loading history...
261
        readfile("schedulers.txt");
262
    }
263
264
    $t = $title?$title:PROJECT;
265
    echo "<title>$t</title>\n";
266
    echo '
267
        <meta charset="utf-8">
268
        <link type="text/css" rel="stylesheet" href="'.secure_url_base().'/bootstrap.min.css" media="all">
269
    ';
270
    if (defined('STYLESHEET')) {
271
        $stylesheet = $url_base.STYLESHEET;
272
        echo "
273
            <link rel=stylesheet type=\"text/css\" href=\"$stylesheet\">
274
        ";
275
    }
276
    if (defined('STYLESHEET2')) {
277
        $stylesheet2 = $url_base.STYLESHEET2;
278
        echo "
279
            <link rel=stylesheet type=\"text/css\" href=\"$stylesheet2\">
280
        ";
281
    }
282
283
    if (defined("SHORTCUT_ICON")) {
284
        echo '<link rel="icon" type="image/x-icon" href="'.SHORTCUT_ICON.'"/>
285
';
286
    }
287
288
    echo "
289
        <link rel=alternate type=\"application/rss+xml\" title=\"$rssname\" href=\"$rsslink\">
290
        </head>
291
    ";
292
    if ($fixed_navbar) {
293
        $body_attrs .= ' style="padding-top:70px"';
294
    }
295
    echo "<body $body_attrs>";
296
    display_cvs_versions();
297
    echo '<div class="container-fluid">
298
    ';
299
300
    switch($title) {    //kludge
301
    case tra("Log in"):
302
    case tra("Create an account"):
303
    case tra("Server status page"):
304
        $is_login_page = true;
305
        break;
306
    default:
0 ignored issues
show
Coding Style introduced by
DEFAULT keyword must be indented 4 spaces from SWITCH keyword
Loading history...
Coding Style introduced by
Comment required for empty DEFAULT case
Loading history...
307
        break;
308
    }
309
    project_banner($title, $url_prefix, $is_main);
310
}
311
}
312
313
// See the comments for page_head()
314
//
315
if (!function_exists("page_tail")){
316
function page_tail(
317
    $show_date=false,
318
        // true for pages that are generated periodically rather than on the fly
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
319
    $url_prefix="",
320
        // use for pages not at top level
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
321
    $is_main=false
322
        // passed to project_footer;
0 ignored issues
show
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 4 spaces but found 8
Loading history...
323
) {
324
    echo "<br>\n";
325
    project_footer($is_main, $show_date, $url_prefix);
326
    echo '
327
        <script src="'.secure_url_base().'/jquery.min.js"></script>
328
        <script src="'.secure_url_base().'/bootstrap.min.js"></script>
329
        </div>
330
        </body>
331
        </html>
332
    ';
333
}
334
}
335
336
function display_cvs_versions(){
337
    global $cvs_version_tracker;
338
    echo "\n<!-- SVN VERSIONS -->\n";
339
    for ($i=0;$i<sizeof($cvs_version_tracker);$i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Coding Style introduced by
Expected 1 space after first semicolon of FOR loop; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after second semicolon of FOR loop; 0 found
Loading history...
Coding Style Performance introduced by
The use of sizeof() inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
340
        echo "<!-- ".$cvs_version_tracker[$i]." -->\n";
341
    }
342
}
343
344
function db_error_page() {
345
    page_head("Database error");
346
    echo tra("A database error occurred while handling your request; please try again later.");
347
    page_tail();
348
}
349
350
function error_page($msg) {
351
    global $generating_xml;
352
    if ($generating_xml) {
353
        xml_error(-1, $msg);
354
    }
355
    page_head(tra("Unable to handle request"));
356
    echo $msg;
357
    page_tail();
358
    exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
359
}
360
361
// takes argument in second and returns a human formatted time string
362
// in the form D days + h Hours + m Min + s sec.
363
364
function time_diff($x, $res=3) {
365
    $days    = (int)($x/86400);
366
    $hours   = (int)(($x-$days*86400)/3600);
367
    $minutes = (int)(($x-$days*86400-$hours*3600)/60);
368
    $seconds = (int)($x % 60);
369
370
    $datestring = "";
371
    if ($days) {
372
        $datestring .= "$days ".tra("days")." ";
373
    }
374
    if ($res>0 && ($hours || strlen($datestring))) {
375
        $datestring .= "$hours ".tra("hours")." ";
376
    }
377
    if ($res>1 && ($minutes || strlen($datestring))) {
378
        $datestring .= "$minutes ".tra("min")." ";
379
    }
380
    if ($res>2 && ($seconds)) {
381
        $datestring .= "$seconds ".tra("sec")." ";
382
    }
383
384
    return $datestring;
385
}
386
387
388
function date_str($x) {
389
    if ($x == 0) return "---";
390
    return gmdate('j M Y', $x);
391
}
392
393
function time_str($x) {
394
    if ($x == 0) return "---";
395
    return gmdate('j M Y, G:i:s', $x) . " UTC";
396
}
397
398
function local_time_str($x) {
399
    if ($x == 0) return "---";
400
    return date('j M Y, H:i T', $x);
401
}
402
403
function pretty_time_str($x) {
404
    return time_str($x);
405
}
406
407
function start_table_str($class="", $style="") {
408
    $s = $style?'style="'.$style.'"':'';
409
    return '<div class="table">
410
      <table '.$s.' width="100%" class="table table-condensed '.$class.'" >
411
    ';
412
}
413
414
function start_table($class="", $style="") {
415
    echo start_table_str($class, $style);
416
}
417
418
function end_table_str() {
419
    return '</table>
420
        </div>
421
    ';
422
}
423
424
function end_table() {
425
    echo end_table_str();
426
}
427
428
// Table header row with unlimited number of columns
429
430
function table_header() {
431
    echo "<tr>\n";
432
    $c = 'class="bg-primary"';
433
    for ($i = 0; $i < func_num_args(); $i++) {
434
        if (is_array(func_get_arg($i))) {
435
            $col = func_get_arg($i);
436
            echo "<th $c ".$col[1].">".$col[0]."</th>\n";
437
        } else {
438
            echo "<th $c>".func_get_arg($i)."</th>\n";
439
        }
440
    }
441
    echo "</tr>\n";
442
}
443
444
// Table row with unlimited number of columns
445
446
function table_row() {
447
    echo "<tr>\n";
448
    for ($i = 0; $i < func_num_args(); $i++) {
449
        if (is_array(func_get_arg($i))) {
450
            $col = func_get_arg($i);
451
            echo "<td ".$col[1].">".$col[0]."</td>\n";
452
        } else {
453
            echo "<td>".func_get_arg($i)."</td>\n";
454
        }
455
    }
456
    echo "</tr>\n";
457
}
458
459
function row1($x, $ncols=2, $class="heading") {
460
    if ($class == "heading") {
461
        echo "<tr><th class=\"bg-primary\" colspan=\"$ncols\">$x</th></tr>\n";
462
    } else {
463
        echo "<tr><td class=\"$class\" colspan=\"$ncols\">$x</td></tr>\n";
464
    }
465
}
466
467
define('NAME_ATTRS', 'class="text-right " style="padding-right:12px"');
468
define('VALUE_ATTRS', 'style="padding-left:12px"');
469
define('VALUE_ATTRS_ERR', 'class="danger" style="padding-left:12px"');
470
471
function row2($x, $y, $show_error=false, $lwidth='40%') {
472
    if ($x==="") $x="<br>";
473
    if ($y==="") $y="<br>";
474
    $attrs = $show_error?VALUE_ATTRS_ERR:VALUE_ATTRS;
475
    echo "<tr>
476
        <td width=\"$lwidth\" ".NAME_ATTRS.">$x</td>
477
        <td $attrs >$y</td>
478
        </tr>
479
    ";
480
}
481
482
function row2_init($x, $y, $lwidth='40%') {
483
    echo '<tr>
484
        <td class="text-right " width="'.$lwidth.'"  style="padding-right: 20px;">'.$x.'</td>
485
        <td '.VALUE_ATTRS.'>'.$y.'
486
    ';
487
}
488
489
function row2_plain($x, $y) {
490
    echo "<tr><td>$x</td><td>$y</td></tr>\n";
491
}
492
493
function rowify($string) {
494
    echo "<tr><td>$string</td></tr>";
495
}
496
497
function row_array($x) {
498
    echo "<tr>\n";
499
    foreach ($x as $h) {
500
        echo "<td>$h</td>\n";
501
    }
502
    echo "</tr>\n";
503
}
504
505
define ('ALIGN_RIGHT', 'style="text-align:right;"');
506
507
function row_heading_array($x, $attrs=null, $class='bg-primary') {
508
    echo "<tr>";
509
    $i = 0;
510
    foreach ($x as $h) {
511
        $a = $attrs?$attrs[$i]:"";
512
        echo "<th $a class=\"$class\">$h</th>";
513
        $i++;
514
    }
515
    echo "</tr>\n";
516
}
517
518
function row_heading($x, $class='bg-primary') {
519
    echo sprintf('<tr><th class="%s" colspan=99>%s</th></tr>
520
        ', $class, $x
521
    );
522
}
523
524
function url_tokens($auth) {
525
    $now = time();
526
    $ttok = md5((string)$now.$auth);
527
    return "&amp;tnow=$now&amp;ttok=$ttok";
528
}
529
530
function form_tokens($auth) {
531
    $now = time();
532
    $ttok = md5((string)$now.$auth);
533
    return "<input type=\"hidden\" name=\"tnow\" value=\"$now\">
534
        <input type=\"hidden\" name=\"ttok\" value=\"$ttok\">
535
    ";
536
}
537
538
function valid_tokens($auth) {
539
    $tnow = get_str('tnow', true);
540
    $ttok = get_str('ttok', true);
541
    if (!$tnow) {
542
        $tnow = $_POST['tnow'];
543
    }
544
    if (!$ttok) {
545
        $ttok = $_POST['ttok'];
546
    }
547
    if (!$tnow) return false;
548
    if (!$ttok) return false;
549
    $t = md5((string)$tnow.$auth);
550
    if ($t != $ttok) return false;
551
    if (time() > $tnow + 86400) return false;
552
    return true;
553
}
554
555
function check_tokens($auth) {
556
    if (valid_tokens($auth)) return;
557
    error_page(
558
        tra("Link has timed out. Please click Back, refresh the page, and try again.")
559
    );
560
}
561
562
// Generates a legal filename from a parameter string.
563
564
function get_legal_filename($name) {
565
    return strtr($name, array(','=>'', ' '=>'_'));
566
}
567
568
// Returns a string containing as many words
569
// (being collections of characters separated by the character $delimiter)
570
// as possible such that the total string length is <= $chars characters long.
571
// If $ellipsis is true, then an ellipsis is added to any sentence which
572
// is cut short.
573
574
function sub_sentence($sentence, $delimiter, $max_chars, $ellipsis=false) {
575
    $words = explode($delimiter, $sentence);
576
    $total_chars = 0;
577
    $trunc = false;
578
    $result = "";
579
580
    foreach ($words as $word) {
581
        if (strlen($result) + strlen($word) > $max_chars) {
582
            $trunc = true;
583
            break;
584
        }
585
        if ($result) {
586
            $result .= " $word";
587
        } else {
588
            $result = $word;
589
        }
590
    }
591
592
    if ($ellipsis && $trunc) {
593
        $result .= "...";
594
    }
595
596
    return $result;
597
}
598
599
// use this for user RAC and result credit
600
//
601
function format_credit($x) {
602
    return number_format($x, 2);
603
}
604
605
// use this when credit is likely to be large, e.g. team RAC
606
//
607
function format_credit_large($x) {
608
    return number_format($x, 0);
609
}
610
611
function host_link($hostid) {
612
    if ($hostid) {
613
        return "<a href=\"show_host_detail.php?hostid=$hostid\">$hostid</a>";
614
    } else {
615
        return "---";
616
    }
617
}
618
619
function open_output_buffer() {
620
    ob_start();
621
    ob_implicit_flush(0);
622
}
623
624
function close_output_buffer($filename) {
625
    $fh = fopen($filename, "w");
626
    $page = ob_get_contents();
627
    ob_end_clean();
628
    fwrite($fh, $page);
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

628
    fwrite(/** @scrutinizer ignore-type */ $fh, $page);
Loading history...
629
    fclose($fh);
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

629
    fclose(/** @scrutinizer ignore-type */ $fh);
Loading history...
630
}
631
632
function bbcode_info() {
633
    return "<br><a href=bbcode.php target=new><small>".tra("Use BBCode tags to format your text")."</small></a>\n";
634
}
635
636
// strip slashes if magic quotes in effect
637
function undo_magic_quotes($x) {
638
    if (get_magic_quotes_gpc()) {
639
        return stripslashes($x);
640
    }
641
    return $x;
642
}
643
644
// check for bogus GET args
645
//
646
function check_get_args($args) {
647
    foreach ($_GET as $key => $val) {
648
        if (!in_array($key, $args)) {
649
            Header("Location: extra_arg_$key.html");
0 ignored issues
show
Coding Style introduced by
Calls to inbuilt PHP functions must be lowercase; expected "header" but found "Header"
Loading history...
650
            die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
651
        }
652
    }
653
}
654
655
// returns null if the arg is optional and missing
656
//
657
function get_int($name, $optional=false) {
658
    $x=null;
659
    if (isset($_GET[$name])) $x = $_GET[$name];
660
    if (!is_numeric($x)) {
661
        if ($optional) {
662
            if ($x) {
663
                Header("Location: non_num_arg.html");
0 ignored issues
show
Coding Style introduced by
Calls to inbuilt PHP functions must be lowercase; expected "header" but found "Header"
Loading history...
664
                die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
665
            }
666
            return null;
667
        } else {
668
            Header("Location: missing_arg_$name.html");
0 ignored issues
show
Coding Style introduced by
Calls to inbuilt PHP functions must be lowercase; expected "header" but found "Header"
Loading history...
669
            die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
670
        }
671
    }
672
    return (int)$x;
673
}
674
675
// returns null if the arg is optional and missing
676
//
677
function post_num($name, $optional=false) {
678
    $x = null;
679
    if (isset($_POST[$name])) $x = $_POST[$name];
680
    if (!is_numeric($x)) {
681
        if ($optional) {
682
            return null;
683
        } else {
684
            error_page("missing or bad parameter: $name; supplied: ".htmlspecialchars($x));
685
        }
686
    }
687
    return (double)$x;
688
}
689
690
// returns null if the arg is optional and missing
691
//
692
function post_int($name, $optional=false) {
693
    $x = post_num($name, $optional);
694
    if (is_null($x)) return null;
695
    $y = (int)$x;
696
    if ($x != $y) {
697
        error_page("param $name must be an integer");
698
    }
699
    return $y;
700
}
701
702
function get_array($name) {
703
    if (isset($_GET[$name])) {
704
        return $_GET[$name];
705
    } else {
706
        return array();
707
    }
708
}
709
710
function get_str($name, $optional=false) {
711
    if (isset($_GET[$name])) {
712
        $x = $_GET[$name];
713
    } else {
714
        if (!$optional) {
715
            error_page("missing or bad parameter: $name");
716
        }
717
        $x = null;
718
    }
719
    return undo_magic_quotes($x);
720
}
721
722
function post_str($name, $optional=false) {
723
    if (isset($_POST[$name])) {
724
        $x = $_POST[$name];
725
    } else {
726
        if (!$optional) {
727
            error_page("missing or bad parameter: $name");
728
        }
729
        $x = null;
730
    }
731
    return undo_magic_quotes($x);
732
}
733
734
function post_arr($name, $optional=false) {
735
    if (isset($_POST[$name]) && is_array($_POST[$name])) {
736
        $x = $_POST[$name];
737
    } else {
738
        if (!$optional) {
739
            error_page("missing or bad parameter: $name");
740
        }
741
        $x = null;
742
    }
743
    return $x;
744
}
745
746
function is_ascii($str) {
747
    // the mb_* functions are not included by default
748
    // return (mb_detect_encoding($passwd) -= 'ASCII');
749
750
    for ($i=0; $i<strlen($str); $i++) {
0 ignored issues
show
Coding Style Performance introduced by
The use of strlen() inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
751
        $c = ord(substr($str, $i));
752
        if ($c < 32 || $c > 127) return false;
753
    }
754
    return true;
755
}
756
757
// This function replaces some often made mistakes while entering numbers
758
// and gives back an error if there are false characters
759
// It will also be checked if the value is within certain borders
760
// @param string &$value reference to the value that should be verified
761
// @param double $low the lowest number of value if verified
762
// @param double $high the highest number of value if verified
763
// @return bool true if $value is numeric and within the defined borders,
764
//   false if $value is not numeric, no changes were made in this case
765
//
766
function verify_numeric(&$value, $low, $high = false) {
767
    $number = trim($value);
768
    $number = str_replace('o', '0', $number);
769
    $number = str_replace('O', '0', $number);
770
    $number = str_replace('x', '', $number); //if someone enters '0x100'
771
    $number = str_replace(',', '.', $number); // replace the german decimal separator
772
    // if no value was entered and this is ok
773
    //
774
    if ($number=='' && !$low) return true;
775
776
    // the supplied value contains alphabetic characters
777
    //
778
    if (!is_numeric($number)) return false;
779
780
    if ($number < $low) return false;
781
782
    if ($high) {
783
        if ($number > $high) return false;
784
    }
785
    $value = (double)$number;
786
    return true;
787
}
788
789
// Generate a "select" element from an array of values
790
//
791
function select_from_array($name, $array, $selection=null, $width=240) {
792
    $out = '<select style="color:#000;"class="form-control input-sm" style="width:'.$width.'px" name="'.$name.'">"';
793
794
    foreach ($array as $key => $value) {
795
        if ($value) {
796
            $out .= "<option ";
797
            if ($key == $selection) {
798
                $out .= "selected ";
799
            }
800
            $out .= "value=\"".$key."\">".$value."</option>\n";
801
        }
802
    }
803
    $out .= "</select>\n";
804
    return $out;
805
}
806
807
// Convert to entities, while preserving already-encoded entities.
808
// Do NOT use if $str contains valid HTML tags.
809
//
810
function boinc_htmlentities($str) {
811
    $str = html_entity_decode($str, ENT_COMPAT, "UTF-8");
812
    $str = htmlentities($str, ENT_COMPAT, "UTF-8");
813
    return $str;
814
}
815
816
function strip_bbcode($string){
817
    return preg_replace("/((\[.+\])+?)(.+?)((\[\/.+\])+?)/","",$string);
818
}
819
820
function current_url() {
821
    $url = "http";
822
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") {
823
        $url .= "s";
824
    }
825
    $url .= "://";
826
    $url .= $_SERVER['SERVER_NAME'];
827
    $url .= ":".$_SERVER['SERVER_PORT'];
828
    if (isset($_SERVER['REQUEST_URI'])) {
829
        $url .= $_SERVER['REQUEST_URI'];
830
    } else {
831
        if ($_SERVER['QUERY_STRING']) {
832
            $url .= "?".$_SERVER['QUERY_STRING'];
833
        }
834
    }
835
    return $url;
836
}
837
838
// Show a single link formatted to look like a button.
839
// @param url The destination URL of the button
840
// @param text The text to display on the button
841
// @param desc The title of the destination - typically used as a popup
842
// @param class The optional CSS class of the button. Defaults to a standard button
843
//
844
845
function button_text($url, $text, $desc=null, $class="btn-success btn-sm") {
846
    if (!$desc) {
847
        $desc = $text;
848
    }
849
    return sprintf(' <a href="%s" title="%s" class="btn %s">%s</a>',
850
        $url, $desc, $class, $text
851
    );
852
}
853
854
function show_button($url, $text, $desc=null, $class="btn-success btn-sm") {
855
    echo button_text($url, $text, $desc=null, $class);
856
}
857
858
// for places with a bunch of buttons, like forum posts
859
//
860
function show_button_small($url, $text, $desc=null) {
861
    echo button_text($url, $text, $desc, "btn-primary btn-xs");
862
}
863
864
// used for showing icons
865
//
866
function show_image($src, $title, $alt, $height=null) {
867
    $h = "";
868
    if ($height) {
869
        $h = "height=\"$height\"";
870
    }
871
    echo "<img class=\"icon\" border=\"0\" title=\"$title\" alt=\"$alt\" src=\"$src\" $h>";
872
}
873
874
function show_project_down() {
875
    global $did_page_head;
876
    if (!$did_page_head) {
877
        page_head(tra("Project down for maintenance"));
878
    }
879
    echo tra(
880
        "%1 is temporarily shut down for maintenance.  Please try again later.",
881
        PROJECT
882
    );
883
    page_tail();
884
    exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
885
}
886
887
function check_web_stopped() {
888
    global $generating_xml;
889
    if (web_stopped()) {
890
        if ($generating_xml) {
891
            xml_error(-183);
892
        } else {
893
            show_project_down();
894
        }
895
    }
896
}
897
898
// Connects to database server and selects database as noted in config.xml
899
// If only read-only access is necessary,
900
// tries instead to connect to <replica_db_host> if tag exists.
901
// DEPRECATED - use boinc_db.inc
902
//
903
function db_init($try_replica=false) {
904
    check_web_stopped();
905
    $retval = db_init_aux($try_replica);
906
    if ($retval == 1) {
907
        echo tra("Unable to connect to database - please try again later");
908
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
909
    }
910
    if ($retval == 2) {
911
        echo tra("Unable to select database - please try again later");
912
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
913
    }
914
    return 0;
915
}
916
917
// return a structure indicating whether project has non-deprecated
918
// apps versions for various resource types,
919
// and with a count of app versions
920
//
921
function get_app_types() {
922
    $t = new StdClass;
923
    $t->cpu = false;
924
    $t->cuda = false;
925
    $t->ati = false;
926
    $t->intel_gpu = false;
927
    $t->count = 0;
928
    $avs = BoincAppVersion::enum("deprecated=0");
929
    foreach ($avs as $av) {
930
        if (strstr($av->plan_class, "ati")) {
931
            $t->ati = true;
932
            $t->count++;
933
        } else if (strstr($av->plan_class, "amd")) {
934
            $t->ati = true;
935
            $t->count++;
936
        } else if (strstr($av->plan_class, "cuda")) {
937
            $t->cuda = true;
938
            $t->count++;
939
        } else if (strstr($av->plan_class, "nvidia")) {
940
            $t->cuda = true;
941
            $t->count++;
942
        } else if (strstr($av->plan_class, "intel_gpu")) {
943
            $t->intel_gpu = true;
944
            $t->count++;
945
        } else {
946
            $t->cpu = true;
947
            $t->count++;
948
        }
949
    }
950
    return $t;
951
}
952
953
// Functions to sanitize GET and POST args
954
955
// "next_url" arguments (must be local, not full URLs)
956
//
957
function sanitize_local_url($x) {
958
    $x = trim($x, "/");
959
    if (strstr($x, "/")) return "";
960
    if (strstr($x, "<")) return "";
961
    if (strstr($x, "\"")) return "";
962
    return $x;
963
}
964
965
// strip HTML tags
966
//
967
function sanitize_tags($x) {
968
    return strip_tags($x);
969
}
970
971
function sanitize_numeric($x) {
972
    if (is_numeric($x)) {
973
        return $x;
974
    } else if (trim($x) == '' ) {
975
        return '';
976
    } else {
977
        return "not numeric";
978
    }
979
}
980
981
function sanitize_email($x) {
982
    if (function_exists('filter_var')) {
983
        return filter_var($x, FILTER_SANITIZE_EMAIL);
984
    } else {
985
        return strip_tags($x);
986
    }
987
}
988
989
function flops_to_credit($f) {
990
    return $f*(200/86400e9);
991
}
992
993
function credit_to_gflop_hours($c) {
994
    return $c/(200/24);
995
}
996
997
function do_download($path,$name="") {
998
    if (strcmp($name,"") == 0) {
999
        $name=basename($path);
1000
    }
1001
    header('Content-Description: File Transfer');
1002
    header('Content-Type: application/octet-stream');
1003
    header('Content-Disposition: attachment; filename='.$name);
1004
    header('Content-Transfer-Encoding: binary');
1005
    header('Expires: 0');
1006
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1007
    header('Pragma: public');
1008
    header('Content-Length: ' . filesize($path));
1009
    flush();
1010
    readfile($path);
1011
}
1012
1013
// if have SSL but not using it, redirect
1014
//
1015
function redirect_to_secure_url() {
1016
    if (defined('SECURE_URL_BASE')
1017
        && strstr(SECURE_URL_BASE, "https://")
1018
        && empty($_SERVER['HTTPS'])
1019
    ) {
1020
        Header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
0 ignored issues
show
Coding Style introduced by
Calls to inbuilt PHP functions must be lowercase; expected "header" but found "Header"
Loading history...
1021
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1022
    }
1023
}
1024
1025
if (php_sapi_name() != "cli") {
1026
    redirect_to_secure_url();
1027
}
1028
1029
function badges_string($is_user, $item, $height) {
1030
    if (DISABLE_BADGES) return null;
1031
    if ($is_user) {
1032
        $bus = BoincBadgeUser::enum("user_id=$item->id");
1033
    } else {
1034
        $bus = BoincBadgeTeam::enum("team_id=$item->id");
1035
    }
1036
    if (!$bus) return null;
1037
    $x = "";
1038
    foreach ($bus as $bu) {
1039
        $badge = BoincBadge::lookup_id($bu->badge_id);
1040
        $x .= "<img title=\"$badge->title\" valign=top height=$height src=$badge->image_url> ";
1041
    }
1042
    return $x;
1043
}
1044
1045
function show_badges_row($is_user, $item) {
1046
    if (BADGE_HEIGHT_LARGE == 0) return;
0 ignored issues
show
introduced by
The condition BADGE_HEIGHT_LARGE == 0 is always false.
Loading history...
1047
    $x = badges_string($is_user, $item, BADGE_HEIGHT_LARGE);
1048
    if ($x) {
1049
        row2("Badges", $x);
1050
    }
1051
}
1052
1053
// If this request is from a BOINC client, return its version as MMmmRR.
1054
// Otherwise return 0.
1055
// Format of user agent string is "BOINC client (windows_x86_64 7.3.17)"
1056
//
1057
function boinc_client_version(){
1058
    if (!array_key_exists('HTTP_USER_AGENT', $_SERVER)) return 0;
1059
    $x = $_SERVER['HTTP_USER_AGENT'];
1060
    $e =  "/BOINC client [^ ]* (\d+).(\d+).(\d+)\)/";
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "="; 2 found
Loading history...
1061
    if (preg_match($e, $x, $matches)) {
1062
        return $matches[1]*10000 + $matches[2]*100 + $matches[3];
1063
    }
1064
    return 0;
1065
}
1066
1067
// output a script for counting chars left in text field
1068
//
1069
function text_counter_script() {
1070
    echo "<script type=\"text/javascript\">
1071
        function text_counter(field, countfield, maxlimit) {
1072
            if (field.value.length > maxlimit) {
1073
                field.value =field.value.substring(0, maxlimit);
1074
            } else {
1075
                countfield.value = maxlimit - field.value.length
1076
            }
1077
        }
1078
        </script>
1079
    ";
1080
}
1081
1082
// return HTML for a textarea with chars-remaining counter.
1083
// Call text_counter_script() before using this.
1084
//
1085
function textarea_with_counter($name, $maxlen, $text) {
1086
    $rem_name = $name."_remaining";
1087
    return "<textarea name=\"$name\" class=\"form-control\" rows=3 id=\"$name\" onkeydown=\"text_counter(this.form.$name, this.form.$rem_name, $maxlen);\"
1088
        onkeyup=\"text_counter(this.form.$name, this.form.$rem_name, $maxlen);\">".$text."</textarea>
1089
        <br><input name=\"$rem_name\" type=\"text\" id=\"$rem_name\" value=\"".($maxlen-strlen($text))."\" size=\"3\" maxlength=\"3\" readonly> ".tra("characters remaining")
1090
    ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected ");" but found ")
;"
Loading history...
1091
}
1092
1093
// convert number MMmmrr to string MM.mm.rr
1094
//
1095
function version_string_maj_min_rel($v) {
1096
    $maj = (int)($v/10000);
1097
    $v -= $maj*10000;
1098
    $min = (int)($v/100);
1099
    $v -= $min*100;
1100
    return sprintf("%d.%d.%d", $maj, $min, $v);
1101
}
1102
1103
function google_search_form($url) {
1104
    echo "
1105
        <nobr>
1106
        <form method=get action=\"https://google.com/search\">
1107
        <input type=hidden name=domains value=\"$url\">
1108
        <input type=hidden name=sitesearch value=\"$url\">
1109
        <input class=small name=q size=20>
1110
        <input class=small type=submit value=".tra("Search").">
1111
        </form>
1112
        </nobr>
1113
    ";
1114
}
1115
1116
// use the following around text with long lines,
1117
// to limit the width and make it more readable.
1118
//
1119
function text_start($width=640) {
1120
    echo sprintf("<div style=\"max-width: %dpx;\">\n", $width);
1121
}
1122
function text_end() {
1123
    echo "</div>\n";
1124
}
1125
1126
function cert_filename() {
1127
    return defined("CERT_FILENAME")?CERT_FILENAME:"cert1.php";
1128
}
1129
1130
$cvs_version_tracker[]="\$Id$";  //Generated automatically - do not edit
1131
1132
?>
1133