1<?php 2// This file is part of BOINC. 3// http://boinc.berkeley.edu 4// Copyright (C) 2014 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 20// functions for display and editing global preferences. 21// Preferences are represented in two ways: 22// - As a PHP structure (usually called $prefs) 23// This has fields run_if_user_active, etc. 24// - As XML (usually called $prefs_xml) 25// 26// This XML has the general structure 27// <global_preferences> 28// <mod_time>...</mod_time> 29// <run_if_user_active/> 30// <work_buf_min_days>1.3</work_buf_min_days> 31// ... 32// <venue name="home"> 33// <run_if_user_active/> 34// ... 35// </venue> 36// </global_preferences> 37// 38 39// Various functions are defined below for converting between these forms, 40// and also to/from HTML form elements 41 42include_once("../inc/prefs_util.inc"); 43include_once("../inc/translation.inc"); 44 45global $cpu_prefs; 46global $disk_prefs; 47global $mem_prefs; 48global $net_prefs; 49 50$cpu_prefs = array( 51 tra("Usage limits"), 52 new PREF_NUM( 53 tra("Use at most"), 54 // xgettext:no-php-format 55 tra("Keep some CPUs free for other applications. Example: 75% means use 6 cores on an 8-core CPU."), 56 "max_ncpus_pct", 57 // xgettext:no-php-format 58 new NUM_SPEC(tra("% of the CPUs"), 1, 100, 100) 59 ), 60 new PREF_NUM( 61 tra("Use at most"), 62 // xgettext:no-php-format 63 tra("Suspend/resume computing every few seconds to reduce CPU temperature and energy usage. Example: 75% means compute for 3 seconds, wait for 1 second, and repeat."), 64 "cpu_usage_limit", 65 // xgettext:no-php-format 66 new NUM_SPEC(tra("% of CPU time"), 1, 100, 100) 67 ), 68 tra("When to suspend"), 69 new PREF_BOOL( 70 tra("Suspend when computer is on battery"), 71 tra("Check this to suspend computing on portables when running on battery power."), 72 "run_on_batteries", 73 false, true 74 ), 75 new PREF_BOOL( 76 tra("Suspend when computer is in use"), 77 tra("Check this to suspend computing and file transfers when you're using the computer."), 78 "run_if_user_active", 79 true, true 80 ), 81 new PREF_BOOL( 82 tra("Suspend GPU computing when computer is in use"), 83 tra("Check this to suspend GPU computing when you're using the computer."), 84 "run_gpu_if_user_active", 85 false, true 86 ), 87 new PREF_NUM( 88 tra("'In use' means mouse/keyboard input in last"), 89 tra("This determines when the computer is considered 'in use'."), 90 "idle_time_to_run", 91 new NUM_SPEC(tra("minutes"), 1, 9999, 3), 92 true 93 ), 94 new PREF_OPT_NUM( 95 tra("Suspend when no mouse/keyboard input in last"), 96 tra("This allows some computers to enter low-power mode when not in use."), 97 "suspend_if_no_recent_input", 98 new NUM_SPEC(tra("minutes"), 0, 9999, 0, 1, 60) 99 ), 100 new PREF_OPT_NUM( 101 tra("Suspend when non-BOINC CPU usage is above"), 102 tra("Suspend computing when your computer is busy running other programs."), 103 "suspend_cpu_usage", 104 new NUM_SPEC("%", 0, 100, 25) 105 ), 106 new PREF_HOUR_RANGE( 107 tra("Compute only between"), 108 tra("Compute only during a particular period each day."), 109 "start_hour", "end_hour" 110 ), 111 tra("Other"), 112 new PREF_NUM( 113 tra("Store at least"), 114 tra("Store at least enough tasks to keep the computer busy for this long."), 115 "work_buf_min_days", 116 new NUM_SPEC(tra("days of work"), 0, 10, .1) 117 ), 118 new PREF_NUM( 119 tra("Store up to an additional"), 120 tra("Store additional tasks above the minimum level. Determines how much work is requested when contacting a project."), 121 "work_buf_additional_days", 122 new NUM_SPEC(tra("days of work"), 0, 10, .5) 123 ), 124 new PREF_NUM( 125 tra("Switch between tasks every"), 126 tra("If you run several projects, BOINC may switch between them this often."), 127 "cpu_scheduling_period_minutes", 128 new NUM_SPEC(tra("minutes"), 1, 9999, 60) 129 ), 130 new PREF_NUM( 131 tra("Request tasks to checkpoint at most every"), 132 tra("This controls how often tasks save their state to disk, so that later they can be continued from that point."), 133 "disk_interval", 134 new NUM_SPEC(tra("seconds"), 0, 9999999, 60) 135 ), 136); 137 138$dp = get_disk_space_config(); 139 140$disk_prefs = array( 141 new PREF_OPT_NUM( 142 tra("Use no more than"), 143 tra("Limit the total amount of disk space used by BOINC."), 144 "disk_max_used_gb", 145 new NUM_SPEC(tra("GB"), 0, 9999999, $dp->disk_max_used_gb, 1, 100) 146 ), 147 new PREF_OPT_NUM( 148 tra("Leave at least"), 149 tra("Limit disk usage to leave this much free space on the volume where BOINC stores data."), 150 "disk_min_free_gb", 151 new NUM_SPEC(tra("GB free"), 0, 9999999, $dp->disk_min_free_gb, 1, 1) 152 ), 153 new PREF_OPT_NUM( 154 tra("Use no more than"), 155 tra("Limit the percentage of disk space used by BOINC on the volume where it stores data."), 156 "disk_max_used_pct", 157 // xgettext:no-php-format 158 new NUM_SPEC(tra("% of total"), 0, 100, $dp->disk_max_used_pct) 159 ), 160); 161 162$mem_prefs = array( 163 new PREF_NUM( 164 tra("When computer is in use, use at most"), 165 tra("Limit the memory used by BOINC when you're using the computer."), 166 "ram_max_used_busy_pct", 167 // xgettext:no-php-format 168 new NUM_SPEC(tra("%"), 1, 100, 50) 169 ), 170 new PREF_NUM( 171 tra("When computer is not in use, use at most"), 172 tra("Limit the memory used by BOINC when you're not using the computer."), 173 "ram_max_used_idle_pct", 174 // xgettext:no-php-format 175 new NUM_SPEC(tra("%"), 1, 100, 90) 176 ), 177 new PREF_BOOL( 178 tra("Leave non-GPU tasks in memory while suspended"), 179 tra("If checked, suspended tasks stay in memory, and resume with no work lost. If unchecked, suspended tasks are removed from memory, and resume from their last checkpoint."), 180 "leave_apps_in_memory", 181 false 182 ), 183 new PREF_NUM( 184 tra("Page/swap file: use at most"), 185 tra("Limit the swap space (page file) used by BOINC."), 186 "vm_max_used_pct", 187 // xgettext:no-php-format 188 new NUM_SPEC(tra("%"), 1, 100, 75) 189 ), 190); 191 192$net_prefs = array( 193 tra("Usage limits"), 194 new PREF_OPT_NUM( 195 tra("Limit download rate to"), 196 tra("Limit the download rate of file transfers."), 197 "max_bytes_sec_down", 198 new NUM_SPEC(tra("KB/second"), 0, 9999999, 0, 1024, 100) 199 ), 200 new PREF_OPT_NUM( 201 tra("Limit upload rate to"), 202 tra("Limit the upload rate of file transfers."), 203 "max_bytes_sec_up", 204 new NUM_SPEC(tra("KB/second"), 0, 9999999, 0, 1024, 100) 205 ), 206 new PREF_NUM2( 207 tra("Limit usage to"), 208 tra("Example: BOINC should transfer at most 2000 MB of data every 30 days."), 209 "daily_xfer_limit_mb", 210 "daily_xfer_period_days", 211 new NUM_SPEC(tra("MB every"), 0, 9999999, 0, 1, 10000), 212 new NUM_SPEC(tra("days"), 0, 9999999, 0, 1, 30) 213 ), 214 tra("When to suspend"), 215 new PREF_HOUR_RANGE( 216 tra("Transfer files only between"), 217 tra("Transfer files only during a particular period each day."), 218 "net_start_hour", "net_end_hour" 219 ), 220 tra("Other"), 221 new PREF_BOOL( 222 tra("Skip data verification for image files"), 223 tra("Check this only if your Internet provider modifies image files. Skipping verification reduces the security of BOINC."), 224 "dont_verify_images", 225 false 226 ), 227 new PREF_BOOL( 228 tra("Confirm before connecting to Internet"), 229 tra("Useful only if you have a modem, ISDN or VPN connection."), 230 "confirm_before_connecting", 231 false 232 ), 233 new PREF_BOOL( 234 tra("Disconnect when done"), 235 tra("Useful only if you have a modem, ISDN or VPN connection."), 236 "hangup_if_dialed", 237 false 238 ), 239); 240 241define("CPU_LIMIT_DESC", tra("Computing")); 242define("DISK_LIMIT_DESC", tra("Disk")); 243define("MEM_LIMIT_DESC", tra("Memory")); 244define("NETWORK_LIMIT_DESC", tra("Network")); 245 246// These texts are used in multiple places in prefs_edit.php and add_venue.php 247define("PREFS_FORM_DESC1", tra("These preferences apply to all the BOINC projects in which you participate.")."<br><br>"); 248define("PREFS_FORM_ERROR_DESC", 249 tra( 250 "%1Unable to update preferences.%2 The values marked in red below were out of range or not numeric.", 251 "<strong>", 252 "</strong>" 253 ). 254 "<br><br>" 255); 256 257global $text; 258global $parse_result; 259global $top_parse_result; 260global $venue_name; 261 262// get default settings for disk space usage so the default user 263// preferences match the settings used by the scheduler. 264// Defaults are set if the tags are missing, they depend on 265// which scheduler is running: 266// - 'old' has the default hardcoded 267// - 'new' uses config settings 268// if running the old scheduler, set <scheduler_disk_space_check_hardcoded> 269// in config.xml so the right default is set for minimum free disk space 270// 271function get_disk_space_config() { 272 global $config; 273 $config = get_config(); 274 $dp = new StdClass; 275 $dp->disk_max_used_gb = parse_config($config, "<default_disk_max_used_gb>"); 276 $dp->disk_max_used_pct = parse_config($config, "<default_disk_max_used_pct>"); 277 $dp->disk_min_free_gb = parse_config($config, "<default_disk_min_free_gb>"); 278 // set some defaults if not found 279 if (!$dp->disk_max_used_gb) $dp->disk_max_used_gb = 0; // no limit 280 if (!$dp->disk_max_used_pct) $dp->disk_max_used_pct = 90; // 90 percent 281 if (!$dp->disk_min_free_gb) $dp->disk_min_free_gb = 1; // 1 GB 282 // set mininimum free space scheduler allows 283 // - depends on which scheduler is running 284 $dp->new_sched_flag = 1; 285 $dp->sched_disk_min_free_gb = $dp->disk_min_free_gb; 286 if (parse_config($config, "scheduler_disk_space_check_hardcoded>")) { 287 $dp->new_sched_flag = 0; 288 $dp->sched_disk_min_free_gb = 0; 289 } 290 291 return $dp; 292} 293 294function group_header($t) { 295 echo "<tr><th class=\"bg-info\">$t</th><td class=\"bg-info\" colspan=4><br></td></tr>\n"; 296} 297 298// functions to parse preferences XML into a struct 299// 300 301function element_start_global($parser, $name, $attrs) { 302 global $top_parse_result; 303 global $parse_result; 304 global $text; 305 global $venue_name; 306 307 switch($name) { 308 case "venue": 309 if (array_key_exists("name", $attrs)) { 310 $venue_name = $attrs["name"]; 311 } else { 312 $venue_name = "home"; 313 } 314 $top_parse_result = $parse_result; 315 $parse_result = default_prefs_global(); 316 break; 317 } 318 $text = ""; 319} 320 321function element_end_global($parser, $name) { 322 global $text; 323 global $parse_result; 324 global $top_parse_result; 325 global $venue_name; 326 global $cpu_prefs; 327 global $disk_prefs; 328 global $mem_prefs; 329 global $net_prefs; 330 331 foreach ($cpu_prefs as $p) { 332 if (is_string($p)) continue; 333 if ($p->xml_parse($parse_result, $name, $text)) { 334 return; 335 } 336 } 337 foreach ($disk_prefs as $p) { 338 if ($p->xml_parse($parse_result, $name, $text)) { 339 return; 340 } 341 } 342 foreach ($mem_prefs as $p) { 343 if ($p->xml_parse($parse_result, $name, $text)) { 344 return; 345 } 346 } 347 foreach ($net_prefs as $p) { 348 if (is_string($p)) continue; 349 if ($p->xml_parse($parse_result, $name, $text)) { 350 return; 351 } 352 } 353 switch($name) { 354 case "venue": 355 $top_parse_result->$venue_name = $parse_result; 356 $parse_result = $top_parse_result; 357 break; 358 case "mod_time": 359 $parse_result->mod_time = $text; 360 break; 361 case "global_preferences": 362 break; 363 default: 364 //echo "Unknown tag: $name\n"; 365 } 366} 367 368function char_handler($parser, $x) { 369 global $text; 370 $text = $text.$x; 371} 372 373 374// state of prefs before parsing; defines prefs for new users 375// 376function default_prefs_global() { 377 global $cpu_prefs; 378 global $disk_prefs; 379 global $mem_prefs; 380 global $net_prefs; 381 382 $p = new StdClass; 383 foreach ($cpu_prefs as $pref) { 384 if (is_string($pref)) continue; 385 $pref->set_default($p); 386 } 387 foreach ($disk_prefs as $pref) { 388 $pref->set_default($p); 389 } 390 foreach ($mem_prefs as $pref) { 391 $pref->set_default($p); 392 } 393 foreach ($net_prefs as $pref) { 394 if (is_string($pref)) continue; 395 $pref->set_default($p); 396 } 397 return $p; 398} 399 400// parse prefs from XML to a struct 401// 402 403function prefs_parse_global($prefs_xml) { 404 global $parse_result; 405 $parse_result = default_prefs_global(); 406 $xml_parser = xml_parser_create(); 407 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0); 408 xml_set_element_handler($xml_parser, "element_start_global", "element_end_global"); 409 xml_set_character_data_handler($xml_parser, "char_handler"); 410 xml_parse($xml_parser, $prefs_xml, 1); 411 return $parse_result; 412} 413 414// Display all venues as columns next to descriptions 415// 416function prefs_show_columns_global($prefs) { 417 global $cpu_prefs; 418 global $disk_prefs; 419 global $mem_prefs; 420 global $net_prefs; 421 422 row_top(CPU_LIMIT_DESC); 423 foreach ($cpu_prefs as $p) { 424 if (is_string($p)) { 425 group_header($p); 426 continue; 427 } 428 $p->show_cols($prefs); 429 } 430 row_top(DISK_LIMIT_DESC); 431 foreach ($disk_prefs as $p) { 432 $p->show_cols($prefs); 433 } 434 row_top(MEM_LIMIT_DESC); 435 foreach ($mem_prefs as $p) { 436 $p->show_cols($prefs); 437 } 438 row_top(NETWORK_LIMIT_DESC); 439 foreach ($net_prefs as $p) { 440 if (is_string($p)) { 441 group_header($p); 442 continue; 443 } 444 $p->show_cols($prefs); 445 } 446 row_links("global", $prefs); 447} 448 449function prefs_show_global($prefs) { 450 global $cpu_prefs; 451 global $disk_prefs; 452 global $mem_prefs; 453 global $net_prefs; 454 455 row1(CPU_LIMIT_DESC); 456 foreach ($cpu_prefs as $p) { 457 if (is_string($p)) { 458 group_header($p); 459 continue; 460 } 461 $p->show($prefs); 462 } 463 row1(DISK_LIMIT_DESC); 464 foreach ($disk_prefs as $p) { 465 $p->show($prefs); 466 } 467 row1(MEM_LIMIT_DESC); 468 foreach ($mem_prefs as $p) { 469 $p->show($prefs); 470 } 471 row1(NETWORK_LIMIT_DESC); 472 foreach ($net_prefs as $p) { 473 if (is_string($p)) { 474 group_header($p); 475 continue; 476 } 477 $p->show($prefs); 478 } 479} 480 481function subset_name($subset) { 482 if ($subset == "global") return tra("Computing"); 483 return PROJECT; 484} 485 486function prefs_display_venue($prefs, $venue, $subset) { 487 global $g_logged_in_user; 488 $tokens = url_tokens($g_logged_in_user->authenticator); 489 $x = false; 490 if (isset($prefs->$venue)) $x = $prefs->$venue; 491 492 if ($x) { 493 start_table(); 494 row_heading(tra("Separate preferences for %1", $venue)); 495 if ($subset == "global") { 496 prefs_show_global($x); 497 } else { 498 prefs_show_project($x); 499 prefs_show_project_specific($x); 500 } 501 row2("<br>", 502 "<a href=prefs_edit.php?venue=$venue&subset=$subset$tokens>".tra("Edit preferences")."</a> 503 | <a href=prefs_remove.php?venue=$venue&subset=$subset$tokens>".tra("Remove")."</a> 504 "); 505 end_table(); 506 echo "</td></tr>\n"; 507 } else { 508 echo "<p><a href=add_venue.php?venue=$venue&subset=$subset$tokens>".tra("Add separate preferences for %1", $venue)."</a>"; 509 } 510} 511 512function print_prefs_display_global($user, $columns=false) { 513 $global_prefs = prefs_parse_global($user->global_prefs); 514 515 echo tra("These settings apply to all computers using this account except") 516 ."<ul><li>" 517 .tra("computers where you have set preferences locally using the BOINC Manager") 518 ."<li>" 519 .tra("Android devices") 520 ."</ul> 521 "; 522 $switch_link = " <font size=\"-1\"><a href=prefs.php?subset=global&cols=". (int)!$columns .">".tra("(Switch view)")."</a></font>"; 523 if ($columns) { 524 echo "<h3>".tra("Combined preferences").$switch_link."</h3>"; 525 start_table(); 526 prefs_show_columns_global($global_prefs); 527 end_table(); 528 529 } else { 530 if (isset($global_prefs->home) || isset($global_prefs->work) || isset($global_prefs->school)) { 531 echo "<h3>".tra("Primary (default) preferences").$switch_link."</h3>"; 532 } 533 start_table(); 534 prefs_show_global($global_prefs); 535 $tokens = url_tokens($user->authenticator); 536 row2("<br>", 537 "<a href=prefs_edit.php?subset=global$tokens>".tra("Edit preferences")."</a> 538 "); 539 end_table(); 540 541 prefs_display_venue($global_prefs, "home", "global"); 542 prefs_display_venue($global_prefs, "school", "global"); 543 prefs_display_venue($global_prefs, "work", "global"); 544 } 545 if (isset($global_prefs->mod_time)) { 546 echo "<p>".tra("Preferences last modified:")." ".pretty_time_str($global_prefs->mod_time)."<p>\n"; 547 } 548} 549 550// This functions is used in prefs_edit.php to be able to display 551// the prefs form in case of an error again. 552// $error and $project_error should be an object of the form: 553// $error->idle_time_to_run=true if an error occurred 554// otherwise false 555// 556function print_prefs_form( 557 $action, $subset, $venue, $user, $prefs, $cols, $error=false, 558 $project_error=false 559){ 560 if ($action == "add") { 561 $script = "add_venue.php"; 562 $submit_value = tra("Add preferences"); 563 } 564 if ($action == "edit") { 565 $script = "prefs_edit.php"; 566 $submit_value = tra("Update preferences"); 567 } 568 echo "<form class=\"form-inline\" action=$script><input type=hidden name=subset value=$subset> 569 ".form_tokens($user->authenticator); 570 if ($venue) { 571 echo "<input type=hidden name=venue value=$venue>\n"; 572 } 573 if ($cols) { 574 echo "<input type=hidden name=cols value=$cols>\n"; 575 } 576 577 start_table(); 578 if ($subset == "global") { 579 prefs_form_global($user, $prefs, $error); 580 } else { 581 prefs_form_project($prefs, $error); 582 if (!$venue) { 583 prefs_form_privacy($user); 584 venue_form($user); 585 } 586 prefs_form_project_specific($prefs->project_specific, $project_error); 587 } 588 589 row2("", "<input class=\"btn btn-primary\" type=submit value=\"$submit_value\" name=\"action\">"); 590 end_table(); 591 echo "</form>\n"; 592} 593 594//////////////////////////////////////////// 595// 596// Functions to display preference subsets as forms 597// 598function prefs_form_global($user, $prefs, $error=false) { 599 global $cpu_prefs; 600 global $disk_prefs; 601 global $mem_prefs; 602 global $net_prefs; 603 604 row1(CPU_LIMIT_DESC); 605 foreach ($cpu_prefs as $p) { 606 if (is_string($p)) { 607 group_header($p); 608 continue; 609 } 610 $p->show_form_row($prefs, $error); 611 } 612 row1(DISK_LIMIT_DESC); 613 foreach ($disk_prefs as $p) { 614 $p->show_form_row($prefs, $error); 615 } 616 row1(MEM_LIMIT_DESC); 617 foreach ($mem_prefs as $p) { 618 $p->show_form_row($prefs, $error); 619 } 620 row1(NETWORK_LIMIT_DESC); 621 foreach ($net_prefs as $p) { 622 if (is_string($p)) { 623 group_header($p); 624 continue; 625 } 626 $p->show_form_row($prefs, $error); 627 } 628} 629 630// returns a set of translated yes/no radio buttons for editing prefs forms 631// Example: prefs_form_radio_buttons("allow_beta_work", $user->allow_beta_work); 632// 633// @param string $name name of the radio buttons 634// @param bool $yesno toggles the preset of the buttons; true=yes, false=no 635// 636function prefs_form_radio_buttons($name, $yesno) { 637 $rb = tra("yes")." <input type=radio name=$name value=yes " 638 .($yesno?"checked":"") 639 ."> ".tra("no")." <input type=radio name=$name value=no " 640 .($yesno?"":"checked") 641 .">\n"; 642 return $rb; 643} 644 645// TODO: make this a subclass of PREF 646// 647define('VENUE_DESC', tra('Default computer location')); 648define('VENUE_TOOLTIP', tra('New computers will use this location for computing and project preferences.')); 649 650function tooltip_row2($t, $x, $y) { 651 echo "<tr title=\"$t\"> 652 <td ".NAME_ATTRS.">$x</td> 653 <td ".VALUE_ATTRS.">$y</td> 654 </tr> 655 "; 656} 657function venue_show($user) { 658 $venue = $user->venue; 659 if ($venue =='') $venue = '---'; 660 tooltip_row2(VENUE_TOOLTIP, VENUE_DESC, $venue); 661} 662 663function venue_form($user) { 664 $n=$h=$w=$s=$m=''; 665 if ($user->venue == '') $n = 'selected'; 666 if ($user->venue == 'home') $h = 'selected'; 667 if ($user->venue == 'work') $w = 'selected'; 668 if ($user->venue == 'school') $s = 'selected'; 669 tooltip_row2( 670 VENUE_TOOLTIP, 671 VENUE_DESC, 672 "<select class=\"form-control input-sm\" name=default_venue> 673 <option value=\"\" $n>--- 674 <option value=home $h>".tra("Home")." 675 <option value=work $w>".tra("Work")." 676 <option value=school $s>".tra("School")." 677 </select> 678 "); 679} 680 681function venue_parse_form(&$user) { 682 $user->venue = $_GET['default_venue']; 683} 684 685//////////////////////////////////////////// 686// 687// Functions to parse form elements, modifying a preferences structure 688// prefs is preferences object to modify 689// returns an object with errorvalues or false in success case 690// 691function prefs_global_parse_form(&$prefs) { 692 global $cpu_prefs; 693 global $disk_prefs; 694 global $mem_prefs; 695 global $net_prefs; 696 697 $error = false; 698 foreach ($cpu_prefs as $p) { 699 if (is_string($p)) continue; 700 $p->parse_form($prefs, $error); 701 } 702 foreach ($disk_prefs as $p) { 703 $p->parse_form($prefs, $error); 704 } 705 foreach ($mem_prefs as $p) { 706 $p->parse_form($prefs, $error); 707 } 708 foreach ($net_prefs as $p) { 709 if (is_string($p)) continue; 710 $p->parse_form($prefs, $error); 711 } 712 return $error; 713} 714 715 716//////////////////////////////////////////// 717// 718// convert prefs from structure to XML 719// 720function global_prefs_make_xml($prefs, $primary=true) { 721 global $cpu_prefs; 722 global $disk_prefs; 723 global $mem_prefs; 724 global $net_prefs; 725 726 $xml = ""; 727 if ($primary) { 728 $xml = "<global_preferences>\n"; 729 $now = time(); 730 $xml = $xml."<mod_time>$now</mod_time>\n"; 731 } 732 733 foreach ($cpu_prefs as $p) { 734 if (is_string($p)) continue; 735 $xml .= $p->xml_string($prefs); 736 } 737 foreach ($disk_prefs as $p) { 738 $xml .= $p->xml_string($prefs); 739 } 740 foreach ($mem_prefs as $p) { 741 $xml .= $p->xml_string($prefs); 742 } 743 foreach ($net_prefs as $p) { 744 if (is_string($p)) continue; 745 $xml .= $p->xml_string($prefs); 746 } 747 748 if (isset($prefs->home)) { 749 $xml = $xml."<venue name=\"home\">\n".global_prefs_make_xml($prefs->home, false)."</venue>\n"; 750 } 751 if (isset($prefs->work)) { 752 $xml = $xml."<venue name=\"work\">\n".global_prefs_make_xml($prefs->work, false)."</venue>\n"; 753 } 754 if (isset($prefs->school)) { 755 $xml = $xml."<venue name=\"school\">\n".global_prefs_make_xml($prefs->school, false)."</venue>\n"; 756 } 757 if ($primary) { 758 $xml = $xml."</global_preferences>\n"; 759 } 760 return $xml; 761} 762 763//////////////////////////////////////////// 764// 765// Update user's prefs in database, from a given structure 766// 767function global_prefs_update(&$user, $prefs) { 768 $prefs_xml = BoincDb::escape_string(global_prefs_make_xml($prefs)); 769 $retval = $user->update("global_prefs='$prefs_xml'"); 770 if (!$retval) { 771 return 1; 772 } 773 $user->global_prefs = $prefs_xml; 774 return 0; 775} 776 777?> 778