Passed
Push — dpa_submit21 ( e4087a )
by David
08:53
created

handle_main()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 47
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 6
eloc 28
c 3
b 1
f 0
nc 4
nop 1
dl 0
loc 47
rs 8.8497
1
<?php
2
3
// This file is part of BOINC.
4
// http://boinc.berkeley.edu
5
// Copyright (C) 2024 University of California
6
//
7
// BOINC is free software; you can redistribute it and/or modify it
8
// under the terms of the GNU Lesser General Public License
9
// as published by the Free Software Foundation,
10
// either version 3 of the License, or (at your option) any later version.
11
//
12
// BOINC is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
// See the GNU Lesser General Public License for more details.
16
//
17
// You should have received a copy of the GNU Lesser General Public License
18
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
19
20
// web interface for remote job submission:
21
// - links to job-submission pages
22
// - Admin (if privileged user)
23
// - manage batches
24
//      view status, get output files, abort, retire
25
// - set 'use only my computers'
26
27
require_once("../inc/submit_db.inc");
28
require_once("../inc/util.inc");
29
require_once("../inc/result.inc");
30
require_once("../inc/submit_util.inc");
31
require_once("../project/project.inc");
32
33
display_errors();
34
35
define("PAGE_SIZE", 20);
36
37
function return_link() {
38
    echo "<p><a href=submit.php>Return to job submission page</a>\n";
39
}
40
41
// get params of in-progress batches; they might not be in progress anymore.
42
//
43
function get_batches_params($batches) {
44
    $b = [];
45
    foreach ($batches as $batch) {
46
        if ($batch->state == BATCH_STATE_IN_PROGRESS) {
47
            $wus = BoincWorkunit::enum("batch = $batch->id");
48
            $b[] = get_batch_params($batch, $wus);
49
        } else {
50
            $b[] = $batch;
51
        }
52
    }
53
    return $b;
54
}
55
56
function state_count($batches, $state) {
57
    $n = 0;
58
    foreach ($batches as $batch) {
59
        if ($batch->state == $state) $n++;
60
    }
61
    return $n;
62
}
63
64
function show_all_link($batches, $state, $limit, $user, $app) {
65
    $n = state_count($batches, $state);
66
    if ($n > $limit) {
67
        if ($user) $userid = $user->id;
68
        else $userid = 0;
69
        if ($app) $appid = $app->id;
70
        else $appid = 0;
71
72
        echo "Showing the most recent $limit of $n batches.
73
            <a href=submit.php?action=show_all&state=$state&userid=$userid&appid=$appid>Show all $n</a>
74
            <p>
75
        ";
76
    }
77
}
78
79
function show_in_progress($batches, $limit, $user, $app) {
80
    echo "<h3>Batches in progress</h3>\n";
81
    $first = true;
82
    $n = 0;
83
    foreach ($batches as $batch) {
84
        if ($batch->state != BATCH_STATE_IN_PROGRESS) continue;
85
        if ($limit && $n == $limit) break;
86
        $n++;
87
        if ($first) {
88
            $first = false;
89
            if ($limit) {
90
                show_all_link($batches, BATCH_STATE_IN_PROGRESS, $limit, $user, $app);
91
            }
92
            start_table('table-striped');
93
            table_header(
94
                "Name",
95
                "ID",
96
                "User",
97
                "App",
98
                "# jobs",
99
                "Progress",
100
                "Submitted"
101
                //"Logical end time<br><small>Determines priority</small>"
102
            );
103
        }
104
        $pct_done = (int)($batch->fraction_done*100);
105
        table_row(
106
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
107
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
108
            $batch->user_name,
109
            $batch->app_name,
110
            $batch->njobs,
111
            "$pct_done%",
112
            local_time_str($batch->create_time)
113
            //local_time_str($batch->logical_end_time)
114
        );
115
    }
116
    if ($first) {
117
        echo "<p>None.\n";
118
    } else {
119
        end_table();
120
    }
121
}
122
123
function show_complete($batches, $limit, $user, $app) {
124
    $first = true;
125
    $n = 0;
126
    foreach ($batches as $batch) {
127
        if ($batch->state != BATCH_STATE_COMPLETE) continue;
128
        if ($limit && $n == $limit) break;
129
        $n++;
130
        if ($first) {
131
            $first = false;
132
            echo "<h3>Completed batches</h3>\n";
133
            if ($limit) {
134
                show_all_link($batches, BATCH_STATE_COMPLETE, $limit, $user, $app);
135
            }
136
            form_start('submit.php', 'get');
137
            form_input_hidden('action', 'retire_multi');
138
            start_table('table-striped');
139
            table_header(
140
                "Name", "ID", "User", "App", "# Jobs", "Submitted", "Select"
141
            );
142
        }
143
        table_row(
144
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
145
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
146
            $batch->user_name,
147
            $batch->app_name,
148
            $batch->njobs,
149
            local_time_str($batch->create_time),
150
            sprintf('<input type=checkbox name=retire_%d>', $batch->id)
151
        );
152
    }
153
    if ($first) {
154
        echo "<p>No completed batches.\n";
155
    } else {
156
        end_table();
157
        form_submit('Retire selected batches');
158
    }
159
}
160
161
function show_aborted($batches, $limit, $user, $app) {
162
    $first = true;
163
    $n = 0;
164
    foreach ($batches as $batch) {
165
        if ($batch->state != BATCH_STATE_ABORTED) continue;
166
        if ($limit && $n == $limit) break;
167
        $n++;
168
        if ($first) {
169
            $first = false;
170
            echo "<h2>Aborted batches</h2>\n";
171
            if ($limit) {
172
                show_all_link($batches, BATCH_STATE_ABORTED, $limit, $user, $app);
173
            }
174
            start_table();
175
            table_header("name", "ID", "user", "app", "# jobs", "submitted");
176
        }
177
        table_row(
178
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
179
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
180
            $batch->user_name,
181
            $batch->app_name,
182
            $batch->njobs,
183
            local_time_str($batch->create_time)
184
        );
185
    }
186
    if (!$first) {
187
        end_table();
188
    }
189
}
190
191
// fill in the app and user names in list of batches
192
// TODO: speed this up by making list of app and user IDs
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
193
// and doing lookup just once.
194
//
195
function fill_in_app_and_user_names(&$batches) {
196
    foreach ($batches as $batch) {
197
        $app = BoincApp::lookup_id($batch->app_id);
198
        if ($app) {
199
            $batch->app_name = $app->name;
200
            if ($batch->description) {
201
                $batch->app_name .= ": $batch->description";
202
            }
203
        } else {
204
            $batch->app_name = "unknown";
205
        }
206
        $user = BoincUser::lookup_id($batch->user_id);
207
        if ($user) {
208
            $batch->user_name = $user->name;
209
        } else {
210
            $batch->user_name = "missing user $batch->user_id";
211
        }
212
    }
213
}
214
215
// show a set of batches
216
//
217
function show_batches($batches, $limit, $user, $app) {
218
    fill_in_app_and_user_names($batches);
219
    $batches = get_batches_params($batches);
220
    show_in_progress($batches, $limit, $user, $app);
221
    show_complete($batches, $limit, $user, $app);
222
    show_aborted($batches, $limit, $user, $app);
223
}
224
225
// show links to per-app job submission forms
226
//
227
function handle_main($user) {
228
    global $web_apps;
229
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
230
    if (!$user_submit) {
231
        error_page("Ask the project admins for permission to submit jobs");
232
    }
233
234
    page_head("Submit jobs");
235
236
    if (!empty($web_apps)) {
237
        // show links to per-app job submission pages
238
        //
239
        foreach ($web_apps as $area => $apps) {
240
            panel($area,
241
                function() use ($apps) {
242
                    foreach ($apps as $app) {
243
                        // show app logo if available
244
                        if ($app[2]) {
245
                            echo sprintf(
246
                                '<a href=%s><img width=100 src=%s></a>&nbsp;',
247
                                $app[1], $app[2]
248
                            );
249
                        } else {
250
                            echo sprintf(
251
                                '<li><a href=%s>%s</a><p>',
252
                                $app[1], $app[0]
253
                            );
254
                        }
255
                    }
256
                }
257
            );
258
        }
259
    }
260
261
    form_start('submit.php');
262
    form_input_hidden('action', 'update_only_own');
263
    form_radio_buttons(
264
        'Jobs you submit can run', 'only_own',
265
        [
266
            [0, 'on any computer'],
267
            [1, 'only on your computers']
0 ignored issues
show
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
268
        ],
269
        $user->seti_id
270
    );
271
    form_submit('Update');
272
    form_end();
273
    page_tail();
274
}
275
276
function handle_show_status($user) {
277
    page_head("Job status");
278
    $batches = BoincBatch::enum("user_id = $user->id order by id desc");
279
    get_batches_params($batches);
280
    show_batches($batches, PAGE_SIZE, $user, null);
281
282
    page_tail();
283
}
284
285
function handle_update_only_own($user) {
286
    $val = get_int('only_own');
287
    $user->update("seti_id=$val");
288
    header("Location: submit.php");
289
}
290
291
// show links for everything the user has admin access to
292
//
293
function handle_admin($user) {
294
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
295
    if (!$user_submit) error_page('no access');
296
    page_head("Administer job submission");
297
    if ($user_submit->manage_all) {
298
        // user can administer all apps
299
        //
300
        echo "<li>All applications<br>
301
            <ul>
302
            <li> <a href=submit.php?action=admin_all>View all batches</a>
303
            <li> <a href=manage_project.php>Manage user permissions</a>
304
            </ul>
305
        ";
306
        $apps = BoincApp::enum("deprecated=0");
307
        foreach ($apps as $app) {
308
            echo "
309
                <li>$app->user_friendly_name<br>
310
                <ul>
311
                <li><a href=submit.php?action=admin_app&app_id=$app->id>View batches</a>
312
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=app_version_form>Manage app versions</a>
313
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=permissions_form>Manage user permissions</a>
314
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=batches_form>Manage batches</a>
315
                </ul>
316
            ";
317
        }
318
    } else {
319
        // see if user can administer specific apps
320
        //
321
        $usas = BoincUserSubmitApp::enum("user_id=$user->id");
322
        foreach ($usas as $usa) {
323
            $app = BoincApp::lookup_id($usa->app_id);
324
            echo "<li>$app->user_friendly_name<br>
325
                <a href=submit.php?action=admin_app&app_id=$app->id>Batches</a>
326
            ";
327
            if ($usa->manage) {
328
                echo "&middot;
329
                    <a href=manage_app.php?app_id=$app->id&action=app_version_form>Versions</a>
330
                ";
331
            }
332
        }
333
    }
334
    echo "</ul>\n";
335
    page_tail();
336
}
337
338
function handle_admin_app($user) {
339
    $app_id = get_int("app_id");
340
    $app = BoincApp::lookup_id($app_id);
341
    if (!$app) error_page("no such app");
342
    if (!has_admin_access($user, $app_id)) {
343
        error_page('no access');
344
    }
345
346
    page_head("Administer batches for $app->user_friendly_name");
347
    $batches = BoincBatch::enum("app_id = $app_id order by id desc");
348
    show_batches($batches, PAGE_SIZE, null, $app);
349
    page_tail();
350
}
351
function handle_admin_all($user) {
352
    page_head("Administer batches (all apps)");
353
    $batches = BoincBatch::enum("true order by id desc");
354
    show_batches($batches, PAGE_SIZE, null, null);
355
    page_tail();
356
}
357
358
359
// show the statics of mem/disk usage of jobs in a batch
360
//
361
function handle_batch_stats($user) {
362
    $batch_id = get_int('batch_id');
363
    $batch = BoincBatch::lookup_id($batch_id);
364
    $results = BoincResult::enum("batch = $batch->id");
365
    page_head("Statistics for batch $batch_id");
366
    $n = 0;
367
    $wss_sum = 0;
368
    $swap_sum = 0;
369
    $disk_sum = 0;
370
    $wss_max = 0;
371
    $swap_max = 0;
372
    $disk_max = 0;
373
    foreach ($results as $r) {
374
        if ($r->outcome != RESULT_OUTCOME_SUCCESS) {
375
            continue;
376
        }
377
        // pre-7.3.16 clients don't report usage info
378
        //
379
        if ($r->peak_working_set_size == 0) {
380
            continue;
381
        }
382
        $n++;
383
        $wss_sum += $r->peak_working_set_size;
384
        if ($r->peak_working_set_size > $wss_max) {
385
            $wss_max = $r->peak_working_set_size;
386
        }
387
        $swap_sum += $r->peak_swap_size;
388
        if ($r->peak_swap_size > $swap_max) {
389
            $swap_max = $r->peak_swap_size;
390
        }
391
        $disk_sum += $r->peak_disk_usage;
392
        if ($r->peak_disk_usage > $disk_max) {
393
            $disk_max = $r->peak_disk_usage;
394
        }
395
    }
396
    if ($n == 0) {
397
        echo "No qualifying results.";
398
        page_tail();
399
        return;
400
    }
401
    text_start(800);
402
    start_table('table-striped');
403
    row2("qualifying results", $n);
404
    row2("mean WSS", size_string($wss_sum/$n));
405
    row2("max WSS", size_string($wss_max));
406
    row2("mean swap", size_string($swap_sum/$n));
407
    row2("max swap", size_string($swap_max));
408
    row2("mean disk usage", size_string($disk_sum/$n));
409
    row2("max disk usage", size_string($disk_max));
410
    end_table();
411
    text_end();
412
    page_tail();
413
}
414
415
// return HTML for a color-coded batch progress bar
416
// green: successfully completed jobs
417
// red: failed
418
// light green: in progress
419
// light gray: unsent
420
//
421
function progress_bar($batch, $wus, $width) {
422
    $nsuccess = $batch->njobs_success;
423
    $nerror = $batch->nerror_jobs;
424
    $nin_prog = $batch->njobs_in_prog;
425
    $nunsent = $batch->njobs - $nsuccess - $nerror - $nin_prog;
426
    $w_success = $width*$nsuccess/$batch->njobs;
427
    $w_fail = $width*$nerror/$batch->njobs;
428
    $w_prog = $width*$nin_prog/$batch->njobs;
429
    $w_unsent = $width*$nunsent/$batch->njobs;
430
    $x = '<table height=20><tr>';
431
    if ($w_fail) {
432
        $x .= "<td width=$w_fail bgcolor=red></td>";
433
    }
434
    if ($w_success) {
435
        $x .= "<td width=$w_success bgcolor=green></td>";
436
    }
437
    if ($w_prog) {
438
        $x .= "<td width=$w_prog bgcolor=lightgreen></td>";
439
    }
440
    if ($w_unsent) {
441
        $x .= "<td width=$w_unsent bgcolor=gray></td>";
442
    }
443
    $x .= "</tr></table>
444
        <strong>
445
        <font color=red>$nerror failed</font> &middot;
446
        <font color=green>$nsuccess completed</font> &middot;
447
        <font color=lightgreen>$nin_prog in progress</font> &middot;
448
        <font color=gray>$nunsent unsent</font>
449
        </strong>
450
    ";
451
    return $x;
452
}
453
454
// show the details of an existing batch
455
//
456
function handle_query_batch($user) {
457
    $batch_id = get_int('batch_id');
458
    $batch = BoincBatch::lookup_id($batch_id);
459
    $app = BoincApp::lookup_id($batch->app_id);
460
    $wus = BoincWorkunit::enum("batch = $batch->id");
461
    $batch = get_batch_params($batch, $wus);
462
    if ($batch->user_id == $user->id) {
463
        $owner = $user;
464
    } else {
465
        $owner = BoincUser::lookup_id($batch->user_id);
466
    }
467
468
    $is_assim_move = is_assim_move($app);
469
470
    page_head("Batch $batch_id");
471
    text_start(800);
472
    start_table();
473
    row2("name", $batch->name);
474
    if ($batch->description) {
475
        row2('description', $batch->description);
476
    }
477
    if ($owner) {
478
        row2('submitter', $owner->name);
479
    }
480
    row2("application", $app?$app->name:'---');
481
    row2("state", batch_state_string($batch->state));
482
    //row2("# jobs", $batch->njobs);
483
    //row2("# error jobs", $batch->nerror_jobs);
484
    //row2("logical end time", time_str($batch->logical_end_time));
485
    if ($batch->expire_time) {
486
        row2("expiration time", time_str($batch->expire_time));
487
    }
488
    if ($batch->njobs) {
489
        row2("progress", progress_bar($batch, $wus, 600));
490
    }
491
    if ($batch->completion_time) {
492
        row2("completed", local_time_str($batch->completion_time));
493
    }
494
    row2("GFLOP/hours, estimated", number_format(credit_to_gflop_hours($batch->credit_estimate), 2));
495
    row2("GFLOP/hours, actual", number_format(credit_to_gflop_hours($batch->credit_canonical), 2));
496
    if (!$is_assim_move) {
497
        row2("Total size of output files",
498
            size_string(batch_output_file_size($batch->id))
499
        );
500
    }
501
    end_table();
502
    echo "<p>";
503
504
    if ($is_assim_move) {
505
        $url = "get_output3.php?action=get_batch&batch_id=$batch->id";
506
    } else {
507
        $url = "get_output2.php?cmd=batch&batch_id=$batch->id";
508
    }
509
    echo "<p>";
510
    show_button($url, "Get zipped output files");
511
    echo "<p>";
512
    switch ($batch->state) {
513
    case BATCH_STATE_IN_PROGRESS:
514
        show_button(
515
            "submit.php?action=abort_batch&batch_id=$batch_id",
516
            "Abort batch"
517
        );
518
        break;
519
    case BATCH_STATE_COMPLETE:
520
    case BATCH_STATE_ABORTED:
521
        show_button(
522
            "submit.php?action=retire_batch&batch_id=$batch_id",
523
            "Retire batch"
524
        );
525
        break;
526
    }
527
    echo "<p>";
528
    show_button("submit.php?action=batch_stats&batch_id=$batch_id",
529
        "Show memory/disk usage statistics"
530
    );
531
532
    echo "<h2>Jobs</h2>\n";
533
    start_table();
534
    $x = [
535
        "Name <br><small>click for details</small>",
536
        "status"
0 ignored issues
show
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
537
    ];
538
    row_heading_array($x);
539
    foreach($wus as $wu) {
540
        switch($wu->status) {
541
        case WU_SUCCESS:
542
            $resultid = $wu->canonical_resultid;
543
            $y = '<font color="green">completed</font>';
544
            break;
545
        case WU_ERROR:
546
            $y = '<font color="red">failed</font>';
547
            break;
548
        case WU_IN_PROGRESS:
549
            $y = '<font color="lightgreen">in progress</font>';
550
            break;
551
        case WU_UNSENT:
552
            $y = '<font color="gray">unsent</font>';
553
        }
554
        $x = [
555
            "<a href=submit.php?action=query_job&wuid=$wu->id>$wu->name</a>",
556
            $y,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $y does not seem to be defined for all execution paths leading up to this point.
Loading history...
557
        ];
558
        row_array($x);
559
    }
560
    end_table();
561
    return_link();
562
    text_end();
563
    page_tail();
564
}
565
566
// Does the assimilator for the given app move output files
567
// to a results/<batchid>/ directory?
568
// This info is stored in the $web_apps data structure in project.inc
569
//
570
function is_assim_move($app) {
571
    global $web_apps;
572
    if (empty($web_apps)) return false;
573
    foreach ($web_apps as $name => $apps) {
574
        foreach ($apps as $web_app) {
575
            if ($web_app[0] == $app->name) {
576
                return $web_app[3];
577
            }
578
        }
579
    }
580
    return false;
581
}
582
583
// show the details of a job, including links to see the output files
584
//
585
function handle_query_job($user) {
586
    $wuid = get_int('wuid');
587
    $wu = BoincWorkunit::lookup_id($wuid);
588
    if (!$wu) error_page("no such job");
589
590
    $app = BoincApp::lookup_id($wu->appid);
591
    $is_assim_move = is_assim_move($app);
592
593
    page_head("Job '$wu->name'");
594
    text_start(800);
595
596
    echo "
597
        <li><a href=workunit.php?wuid=$wuid>Workunit details</a>
598
        <p>
599
        <li><a href=submit.php?action=query_batch&batch_id=$wu->batch>Batch details</a>
600
    ";
601
602
    echo "<h2>Job instances</h2>\n";
603
    start_table('table-striped');
604
    table_header(
605
        "ID<br><small>click for details and stderr</small>",
606
        "State",
607
        "Output files"
608
    );
609
    $results = BoincResult::enum("workunitid=$wuid");
610
    $upload_dir = parse_config(get_config(), "<upload_dir>");
611
    $fanout = parse_config(get_config(), "<uldl_dir_fanout>");
612
    foreach($results as $result) {
613
        $x = [
614
            "<a href=result.php?resultid=$result->id>$result->id</a>",
615
            state_string($result)
0 ignored issues
show
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
616
        ];
617
        $i = 0;
618
        if ($result->server_state == RESULT_SERVER_STATE_OVER) {
619
            $phys_names = get_outfile_phys_names($result);
620
            $log_names = get_outfile_log_names($result);
621
            for ($i=0; $i<count($phys_names); $i++) {
0 ignored issues
show
Coding Style Performance introduced by
The use of count() 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...
Performance Best Practice introduced by
It seems like you are calling the size function count() 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...
622
                if ($is_assim_move) {
623
                    // file is in
624
                    // project/results/<batchid>/<wu_name>__file_<log_name>
625
                    $path = sprintf('results/%s/%s__file_%s',
626
                        $wu->batch, $wu->name, $log_names[$i]
627
                    );
628
                    $x[] = "<a href=get_output3.php?action=get_file&path=$path>view</a> &middot; <a href=get_output3.php?action=get_file&path=$path&download=1>download</a>";
629
                } else {
630
                    $path = dir_hier_path(
631
                        $phys_names[$i], $upload_dir, $fanout
632
                    );
633
                    if (file_exists($path)) {
634
                        $url = sprintf(
635
                            'get_output2.php?cmd=result&result_id=%d&file_num=%d',
636
                            $result->id, $i
637
                        );
638
                        $s = stat($path);
639
                        $size = $s['size'];
640
                        $x[] = sprintf('<a href=%s>%s</a> (%s bytes)<br/>',
641
                            $url,
642
                            $log_names[$i],
643
                            number_format($size)
644
                        );
645
                    } else {
646
                        $x[] = sprintf("file '%s' is missing", $log_names[$i]);
647
                    }
648
                }
649
            }
650
        } else {
651
            $x[] = '---';
652
        }
653
        row_array($x);
654
    }
655
    end_table();
656
657
    // show input files
658
    //
659
    echo "<h2>Input files</h2>\n";
660
    $x = "<in>".$wu->xml_doc."</in>";
661
    $x = simplexml_load_string($x);
662
    start_table('table-striped');
663
    table_header("Name<br><small>(click to view)</small>", "Size (bytes)");
664
    foreach ($x->workunit->file_ref as $fr) {
665
        $pname = (string)$fr->file_name;
666
        $lname = (string)$fr->open_name;
667
        foreach ($x->file_info as $fi) {
668
            if ((string)$fi->name == $pname) {
669
                table_row(
670
                    "<a href=$fi->url>$lname</a>",
671
                    $fi->nbytes
672
                );
673
                break;
674
            }
675
        }
676
    }
677
678
    end_table();
679
    text_end();
680
    return_link();
681
    page_tail();
682
}
683
684
// is user allowed to retire or abort this batch?
685
//
686
function check_access($user, $batch) {
687
    if ($user->id == $batch->user_id) return;
688
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
689
    if ($user_submit->manage_all) return;
690
    $usa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$batch->app_id");
691
    if ($usa->manage) return;
692
    error_page("no access");
693
}
694
695
function handle_abort_batch() {
696
    $batch_id = get_int('batch_id');
697
    $batch = BoincBatch::lookup_id($batch_id);
698
    if (!$batch) error_page("no such batch");
699
    check_access($user, $batch);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
700
701
    if (get_int('confirmed', true)) {
702
        abort_batch($batch);
703
        page_head("Batch aborted");
704
        return_link();
705
        page_tail();
706
    } else {
707
        page_head("Confirm abort batch");
708
        echo "
709
            Aborting a batch will cancel all unstarted jobs.
710
            Are you sure you want to do this?
711
            <p>
712
        ";
713
        show_button(
714
            "submit.php?action=abort_batch&batch_id=$batch_id&confirmed=1",
715
            "Yes - abort batch"
716
        );
717
        return_link();
718
        page_tail();
719
    }
720
}
721
722
function handle_retire_batch($user) {
723
    $batch_id = get_int('batch_id');
724
    $batch = BoincBatch::lookup_id($batch_id);
725
    if (!$batch) error_page("no such batch");
726
    check_access($user, $batch);
727
728
    if (get_int('confirmed', true)) {
729
        retire_batch($batch);
730
        page_head("Batch retired");
731
        return_link();
732
        page_tail();
733
    } else {
734
        page_head("Confirm retire batch");
735
        echo "
736
            Retiring a batch will remove all of its output files.
737
            Are you sure you want to do this?
738
            <p>
739
        ";
740
        show_button(
741
            "submit.php?action=retire_batch&batch_id=$batch_id&confirmed=1",
742
            "Yes - retire batch"
743
        );
744
        return_link();
745
        page_tail();
746
    }
747
}
748
749
function handle_retire_multi($user) {
750
    $batches = BoincBatch::enum(
751
        sprintf('user_id=%d and state=%d', $user->id, BATCH_STATE_COMPLETE)
752
    );
753
    page_head('Retiring batches');
754
    foreach ($batches as $batch) {
755
        $x = sprintf('retire_%d', $batch->id);
756
        if (get_str($x, true) == 'on') {
757
            retire_batch($batch);
758
            echo "<p>retired batch $batch->name\n";
759
        }
760
    }
761
    return_link();
762
    page_tail();
763
}
764
765
function show_batches_in_state($batches, $state) {
766
    switch ($state) {
767
    case BATCH_STATE_IN_PROGRESS:
768
        page_head("Batches in progress");
769
        show_in_progress($batches, 0, null, null);
770
        break;
771
    case BATCH_STATE_COMPLETE:
772
        page_head("Completed batches");
773
        show_complete($batches, 0, null, null);
774
        break;
775
    case BATCH_STATE_ABORTED:
776
        page_head("Aborted batches");
777
        show_aborted($batches, 0, null, null);
778
        break;
779
    }
780
    page_tail();
781
}
782
783
function handle_show_all($user) {
784
    $userid = get_int("userid");
785
    $appid = get_int("appid");
786
    $state = get_int("state");
787
    if ($userid) {
788
        // user looking at their own batches
789
        //
790
        if ($userid != $user->id) error_page("wrong user");
791
        $batches = BoincBatch::enum("user_id = $user->id and state=$state order by id desc");
792
        fill_in_app_and_user_names($batches);
793
        show_batches_in_state($batches, $state);
794
    } else {
795
        // admin looking at batches
796
        //
797
        if (!has_admin_access($user, $appid)) {
798
            error_page('no access');
799
        }
800
        if ($appid) {
801
            $app = BoincApp::lookup_id($appid);
802
            if (!$app) error_page("no such app");
803
            $batches = BoincBatch::enum("app_id = $appid and state=$state order by id desc");
804
        } else {
805
            $batches = BoincBatch::enum("state=$state order by id desc");
806
        }
807
        fill_in_app_and_user_names($batches);
808
        show_batches_in_state($batches, $state);
809
    }
810
}
811
812
$user = get_logged_in_user();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $user is correct as get_logged_in_user() 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...
813
814
$action = get_str('action', true);
815
816
switch ($action) {
817
case '': handle_main($user); break;
818
case 'abort_batch': handle_abort_batch($user); break;
0 ignored issues
show
Unused Code introduced by
The call to handle_abort_batch() has too many arguments starting with $user. ( Ignorable by Annotation )

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

818
case 'abort_batch': /** @scrutinizer ignore-call */ handle_abort_batch($user); break;

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
819
case 'admin': handle_admin($user); break;
820
case 'admin_app': handle_admin_app($user); break;
821
case 'admin_all': handle_admin_all($user); break;
822
case 'batch_stats': handle_batch_stats($user); break;
823
case 'query_batch': handle_query_batch($user); break;
824
case 'query_job': handle_query_job($user); break;
825
case 'retire_batch': handle_retire_batch($user); break;
826
case 'retire_multi': handle_retire_multi($user); break;
827
case 'show_all': handle_show_all($user); break;
828
case 'status': handle_show_status($user); break;
829
case 'update_only_own': handle_update_only_own($user); break;
830
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
DEFAULT case must have a breaking statement
Loading history...
831
    error_page("no such action $action");
832
}
833
834
?>
835