|
|
1.1 ! root 1: <? // -*- Mode: PHP; -*- ! 2: ! 3: /** ! 4: * Copyright (C) 2009 Marty Connor <[email protected]>. ! 5: * Copyright (C) 2009 Entity Cyber, Inc. ! 6: * ! 7: * This program is free software; you can redistribute it and/or ! 8: * modify it under the terms of the GNU General Public License as ! 9: * published by the Free Software Foundation; either version 2 of the ! 10: * License, or any later version. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, but ! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 15: * General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU General Public License ! 18: * along with this program; if not, write to the Free Software ! 19: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 20: */ ! 21: ! 22: // Include table of user-configurable iPXE options ! 23: require_once "flag-table.php"; ! 24: ! 25: // Include user-shadowable globals ! 26: require_once "globals.php"; ! 27: ! 28: // Allow user to shadow globals ! 29: if ( is_file ( 'local-config.php' ) ) { ! 30: include_once "local-config.php"; ! 31: } ! 32: ! 33: //// ! 34: // General utility functions ! 35: //// ! 36: ! 37: /** ! 38: * Remove undesirable characters from a given string ! 39: * ! 40: * Certain characters have the potential to be used for ! 41: * malicious purposes by web-based attackers. This routine ! 42: * filters out such characters. ! 43: * ! 44: * @param string $s supplied string ! 45: * ! 46: * @return string returned string with unwanted characters ! 47: * removed ! 48: */ ! 49: function cleanstring ( $s ) ! 50: { ! 51: $len = strlen ( $s ); ! 52: if ( $len > 80 ) { ! 53: $s = substr ( $s, 0, 80 ); ! 54: } ! 55: ! 56: $s = trim ( $s ); ! 57: $pos = 0; ! 58: $result = ""; ! 59: ! 60: while ( $pos < $len ) { ! 61: $ltr = ord ( ucfirst ( $s[$pos] ) ); ! 62: if ( ( $ltr >= ord ( "A" ) ) && ( $ltr <= ord ( "Z" ) ) || ! 63: ( $ltr >= ord ( "0" ) ) && ( $ltr <= ord ( "9" ) ) || ! 64: ( $ltr == ord ( "." ) ) && ( strlen ( $result ) > 0 ) || ! 65: ( $ltr == ord ( "_" ) ) || ! 66: ( $ltr == ord ( "+" ) ) || ! 67: ( $ltr == ord ( ":" ) ) || ! 68: ( $ltr == ord ( "/" ) ) || ! 69: ( $ltr == ord ( "-" ) ) ) { ! 70: $result .= $s[$pos]; ! 71: } ! 72: $pos++; ! 73: } ! 74: return $result; ! 75: } ! 76: ! 77: /** ! 78: * Return URL of the currently running script, minus the filename ! 79: * ! 80: * @return string the URL of the currently running script, minus the filename ! 81: */ ! 82: function curDirURL () ! 83: { ! 84: $dir = dirname ( $_SERVER['PHP_SELF'] ); ! 85: ! 86: if ( $dir == "." || $dir == "/" ) { ! 87: $dir = ""; ! 88: } ! 89: ! 90: $isHTTPS = ( isset ( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" ); ! 91: $port = ( isset($_SERVER["SERVER_PORT"] ) && ! 92: ( ( !$isHTTPS && $_SERVER["SERVER_PORT"] != "80" ) || ! 93: ( $isHTTPS && $_SERVER["SERVER_PORT"] != "443" ) ) ); ! 94: ! 95: $port = ( $port ) ? ':' . $_SERVER["SERVER_PORT"] : ''; ! 96: ! 97: $dest = ( $isHTTPS ? 'https://' : 'http://' ) . ! 98: $_SERVER["SERVER_NAME"] . $dir . "/"; ! 99: ! 100: return $dest; ! 101: } ! 102: ! 103: /** ! 104: * Extract NIC families and associated ROM PCI IDs from the src/bin/NIC file. ! 105: * ! 106: * $src_dir must contain the path of the iPXE src directory for this build ! 107: * ! 108: * @return array[0] array $new_nics ! 109: * @return array[1] array $roms ! 110: */ ! 111: function parse_nic_file () ! 112: { ! 113: global $src_dir; ! 114: ! 115: $fd = fopen ( "$src_dir/bin/NIC", "r" ); ! 116: if ( ! $fd ) { ! 117: die ( "Missing src/bin/NIC file. 'make bin/NIC'" ); ! 118: } ! 119: ! 120: $nics = array (); ! 121: $roms = array (); ! 122: $nic = ""; ! 123: ! 124: while ( !feof ( $fd ) ) { ! 125: ! 126: $line = trim ( fgets ( $fd, 200 ) ); ! 127: ! 128: $first_eight_chars = substr ( $line, 0, 8 ); ! 129: settype ( $first_eight_chars, "string" ); ! 130: ! 131: if ( strpos ( $first_eight_chars, "family" ) === 0 ) { ! 132: ! 133: // get pathname of NIC driver ! 134: list ( $dummy, $nic ) = split( "[ \t]+", $line ); ! 135: settype ( $nic, "string" ); ! 136: ! 137: // extract filename name of driver from pathname ! 138: $nic = substr ( $nic, strrpos ( $nic, "/" ) + 1, ! 139: strlen ( $nic ) - strrpos ( $nic, "/" ) + 1 ); ! 140: ! 141: $nics[$nic] = $nic; ! 142: ! 143: // For each ISA NIC, there can only be one ROM variant ! 144: $roms[$nic] = $nic; ! 145: } ! 146: ! 147: // If the first 8 digits of the line are hex digits ! 148: // add this rom to the current nic family. ! 149: ! 150: if ( ( strlen ( $first_eight_chars ) == 8 ) ! 151: && ( ctype_xdigit ( $first_eight_chars ) ) ! 152: && ( $nic != "" ) ) { ! 153: ! 154: $roms[$first_eight_chars] = $nic; ! 155: } ! 156: } ! 157: fclose ( $fd ); ! 158: ! 159: // put most NICs in nice alpha order for menu ! 160: ksort ( $nics ); ! 161: ! 162: // add special cases to the top ! 163: ! 164: $new_nics = array ( "all-drivers" => "ipxe", ! 165: "undionly" => "undionly", ! 166: "undi" => "undi", ! 167: ); ! 168: ! 169: foreach ( $nics as $key => $value ) { ! 170: // skip the undi driver ! 171: if ( $key != "undi" ) { ! 172: $new_nics[$key] = $value; ! 173: } ! 174: } ! 175: ! 176: return array ( $new_nics, $roms ); ! 177: } ! 178: ! 179: //// ! 180: // HTML form utility functions ! 181: //// ! 182: ! 183: /** ! 184: * Return html code to create hidden form input fields ! 185: * ! 186: * @param string $flag name of form variable to set ! 187: * @param string $value value to give form variable ! 188: * ! 189: * @return string html code for given hidden form input field ! 190: */ ! 191: function hidden ( $flag, $value ) ! 192: { ! 193: $value = htmlentities ( $value ); ! 194: return "<input type=\"hidden\" value=\"$value\" name=\"$flag\"></input>"; ! 195: } ! 196: ! 197: /** ! 198: * Return html code to create checkbox form input fields ! 199: * ! 200: * @param string $flag name of form variable to set ! 201: * @param string $value "on" means box should be checked ! 202: * ! 203: * @return string html code for given hidden form input field ! 204: */ ! 205: function checkbox ( $flag, $value ) ! 206: { ! 207: return "<input type=\"checkbox\" value=\"on\" name=\"$flag\"" . ! 208: ($value == "on" ? " checked>" : ">" ); ! 209: } ! 210: ! 211: /** ! 212: * Return html code to create text form input fields ! 213: * ! 214: * @param string $flag name of form variable to set ! 215: * @param string $value initial contents of field ! 216: * @param string $size size in characters of text box ! 217: * ! 218: * @return string html code for given text input field ! 219: */ ! 220: function textbox ( $flag, $value, $size ) ! 221: { ! 222: $value = htmlentities ( $value ); ! 223: return "<input type=\"text\" size=\"$size\" value=\"$value\" name=\"$flag\">"; ! 224: } ! 225: ! 226: /** ! 227: * Return html code to create textarea form fields ! 228: * ! 229: * @param string $flag name of form variable to set ! 230: * @param string $value initial contents of textarea ! 231: * @param string $rows height of text area in rows ! 232: * @param string $cols width of text area in columns ! 233: * ! 234: * @return string html code for given textarea input field ! 235: */ ! 236: function textarea ( $flag, $value, $rows, $cols ) ! 237: { ! 238: $value = htmlentities ( $value ); ! 239: return "<textarea name=\"$flag\" rows=\"$rows\" cols=\"$cols\">" ! 240: . $value . "</textarea>"; ! 241: } ! 242: ! 243: /** ! 244: * Return html code to create select (menu) form fields ! 245: * ! 246: * Use array of strings as menu choices ! 247: * ! 248: * @param string $flag name of form variable to set ! 249: * @param array $options array of strings representing choices ! 250: * @param string $value value of choice to select in menu ! 251: * ! 252: * @return string html code for given select (menu) input field ! 253: */ ! 254: function menubox ( $name, $options, $value ) ! 255: { ! 256: $s="<select name=\"$name\">"; ! 257: ! 258: foreach ( $options as $ignore => $option ) { ! 259: if ( !$value ) $value = $option; ! 260: $s .= "<option" . ( $option == $value ? " selected>" : ">" ) . ! 261: htmlentities ( $option ) . "</option>"; ! 262: } ! 263: return $s . "</select>"; ! 264: } ! 265: ! 266: /** ! 267: * Return html code to create select (menu) form fields ! 268: * ! 269: * Use indices of array of strings as menu choices rather than ! 270: * the values pointed to by the indicies. ! 271: * ! 272: * @param string $flag name of form variable to set ! 273: * @param array $options array of strings representing choices ! 274: * @param string $value value of choice to select in menu ! 275: * ! 276: * @return string html code for given select (menu) input field ! 277: */ ! 278: function keys_menubox ( $name, $options, $value ) ! 279: { ! 280: $s="<select name=\"$name\">"; ! 281: ! 282: foreach ( $options as $option => $ignore ) { ! 283: if ( !$value ) $value = $option; ! 284: $s .= "<option" . ( $option == $value ? " selected>" : ">" ) . ! 285: htmlentities ( $option ) . "</option>"; ! 286: } ! 287: return $s . "</select>"; ! 288: } ! 289: ! 290: //// ! 291: // Flag (compile option) handling functions ! 292: //// ! 293: ! 294: /** ! 295: * Return default compile options (flags) ! 296: * ! 297: * Initial compile options are in a global called $flag_table. ! 298: * Create and return an array containing the ones we want. ! 299: * ! 300: * @return array default compile options (flags) ! 301: */ ! 302: function default_flags () ! 303: { ! 304: global $flag_table; ! 305: ! 306: $flags = array (); ! 307: ! 308: foreach ( $flag_table as $key => $props ) { ! 309: ! 310: $flag = $props["flag"]; ! 311: $type = $props["type"]; ! 312: ! 313: // Fields like headers have no "value" property ! 314: if ( isset ( $props["value"] ) ) { ! 315: $flags[$flag] = $props["value"]; ! 316: } ! 317: } ! 318: return $flags; ! 319: } ! 320: ! 321: /** ! 322: * Return combination of default and user compile options (flags) ! 323: * ! 324: * Initial compile options are in a global called $flag_table. ! 325: * Compile options may have been changed via form input. We return ! 326: * an array with either the default value of each option or a user ! 327: * supplied value from form input. ! 328: * ! 329: * @return array combined default and user supplied compile options (flags) ! 330: */ ! 331: function get_flags () ! 332: { ! 333: global $flag_table; ! 334: ! 335: $flags = default_flags (); ! 336: ! 337: if ( ! isset ( $_POST["use_flags"] ) ) ! 338: return $flags; ! 339: ! 340: foreach ( $flag_table as $key => $props ) { ! 341: ! 342: $flag = $props["flag"]; ! 343: $type = $props["type"]; ! 344: ! 345: if ( isset ( $_POST["$flag"] ) ) { ! 346: $flags[$flag] = $_POST["$flag"]; ! 347: if ( $type == "integer-hex" ) { ! 348: if ( strtolower ( substr ( $flags[$flag], 0, 2 ) ) != "0x" ) { ! 349: $flags[$flag] = "0x" . $flags[$flag]; ! 350: } ! 351: } ! 352: } else if ( $type == "on/off" ) { ! 353: // Unchecked checkboxes don't pass any POST value ! 354: // so we must check for them specially. At this ! 355: // point we know that there is no $_POST value set ! 356: // for this option. If it is a checkbox, this means ! 357: // it is unchecked, so record that in $flags so we ! 358: // can later generate an #undef for this option. ! 359: $flags[$flag] = "off"; ! 360: } ! 361: } ! 362: return $flags; ! 363: } ! 364: ! 365: /** ! 366: * Output given value in appropriate format for iPXE config file ! 367: * ! 368: * iPXE config/*.h files use C pre-processor syntax. Output the given ! 369: * compile option in a format appropriate to its type ! 370: * ! 371: * @param string $key index into $flag_table for given compile option ! 372: * @param string $value value we wish to set compile option to ! 373: * ! 374: * @return string code to set compile option to given value ! 375: */ ! 376: function pprint_flag ( $key, $value ) ! 377: { ! 378: global $flag_table; ! 379: ! 380: // Determine type of given compile option (flag) ! 381: $type = $flag_table[$key]["type"]; ! 382: $s = ""; ! 383: ! 384: if ( $type == "on/off" && $value == "on" ) { ! 385: $s = "#define $key"; ! 386: } else if ( $type == "on/off" && $value != "on" ) { ! 387: $s = "#undef $key"; ! 388: } else if ( $type == "string" ) { ! 389: $s = ( "#define $key \"" . cleanstring ( $value ) . "\"" ); ! 390: } else if ($type == "qstring" ) { ! 391: $s = ( "#define $key \\\"" . cleanstring ( $value ) . "\\\"" ); ! 392: } else { ! 393: $s = "#define $key " . cleanstring ( $value ); ! 394: } ! 395: ! 396: return $s; ! 397: } ! 398: ! 399: /** ! 400: * Output html code to display all compile options as a table ! 401: * ! 402: * @param array $flags array of compile options ! 403: * ! 404: * @return void ! 405: */ ! 406: function echo_flags ( $flags ) ! 407: { ! 408: global $flag_table; ! 409: ! 410: echo "<table>\n"; ! 411: ! 412: foreach ( $flag_table as $key => $props ) { ! 413: ! 414: // Hide parameters from users that should not be changed. ! 415: $hide_from_user = isset ( $props["hide_from_user"] ) ? $props["hide_from_user"] : "no"; ! 416: ! 417: $flag = $props["flag"]; ! 418: $type = $props["type"]; ! 419: ! 420: $value = isset ( $flags[$flag] ) ? $flags[$flag] : ''; ! 421: ! 422: if ( $hide_from_user == "yes" ) { ! 423: ! 424: // Hidden flags cannot not be set by the user. We use hidden form ! 425: // fields to keep them at their default values. ! 426: if ( $type != "header" ) { ! 427: echo hidden ( $flag, $value ); ! 428: } ! 429: ! 430: } else { ! 431: ! 432: // Flag (iPXE compile option) should be displayed to user ! 433: ! 434: if ( $type == "header" ) { ! 435: ! 436: $label = $props["label"]; ! 437: echo "<td colspan=2><hr><h3>$label</h3><hr></td>"; ! 438: ! 439: } else if ($type == "on/off" ) { ! 440: ! 441: echo "<td>", checkbox ( $flag, $value ), "</td><td><strong>$flag</strong></td>"; ! 442: ! 443: } else { // don't display checkbox for non-on/off flags ! 444: ! 445: echo "<td> </td><td><strong>$flag: </strong>"; ! 446: ! 447: if ($type == "choice" ) { ! 448: $options = $props["options"]; ! 449: echo menubox($flag, $options, $value); ! 450: ! 451: } else { ! 452: ! 453: echo textbox($flag, $value, ($type == "integer" || ! 454: $type == "integer-hex" ! 455: ? 7 : 25)); ! 456: } ! 457: echo "</td>"; ! 458: } ! 459: echo "</tr>\n"; ! 460: ! 461: if ( $type != "header" ) { ! 462: echo "<tr><td> </td>"; ! 463: echo "<td>\n"; ! 464: if ( is_file ( "doc/$flag.html" ) ) { ! 465: include_once "doc/$flag.html"; ! 466: } ! 467: echo "\n</td></tr>\n"; ! 468: } ! 469: } ! 470: } ! 471: echo "</table>"; ! 472: } ! 473: ! 474: /** ! 475: * Return an array of configuration sections used in all compile options ! 476: * ! 477: * $flag_table, the global list of compile options contains a 'cfgsec' ! 478: * property for each flag we are interested in. We return a list of ! 479: * all the unique cfgsec options we find in $flag_table. ! 480: * ! 481: * @return array an array of strings representing all unique cfgsec values ! 482: * found in $flag_table ! 483: */ ! 484: function get_flag_cfgsecs () ! 485: { ! 486: global $flag_table; ! 487: $cfgsecs = array (); ! 488: ! 489: foreach ( $flag_table as $key => $props ) { ! 490: if ( isset ( $props['cfgsec'] ) ) { ! 491: $cfgsec = $props["cfgsec"]; ! 492: $cfgsecs[$cfgsec] = $cfgsec; ! 493: } ! 494: } ! 495: return $cfgsecs; ! 496: } ! 497: ! 498: //// ! 499: // File and directory handling functions ! 500: //// ! 501: ! 502: /** ! 503: * Create a copy of a given source directory to a given destination ! 504: * ! 505: * Since we are going to modify the source directory, we create a copy ! 506: * of the directory with a unique name in the given destination directory. ! 507: * We supply a prefix for the tempnam call to prepend to the random filename ! 508: * it generates. ! 509: * ! 510: * @param string $src source directory ! 511: * @param string $dst destination directory ! 512: * @param string $prefix string to append to directory created ! 513: * ! 514: * @return string absolute path to destination directory ! 515: */ ! 516: function mktempcopy ( $src, $dst, $prefix ) ! 517: { ! 518: if ( $src[0] != "/" ) { ! 519: $src = dirname ( $_SERVER['SCRIPT_FILENAME'] ) . "/" . $src; ! 520: } ! 521: ! 522: // Create a file in the given destination directory with a unique name ! 523: $dir = tempnam ( $dst, $prefix ); ! 524: ! 525: // Delete the file just created, since it would interfere with the copy we ! 526: // are about to do. We only care that the dir name we copy to is unique. ! 527: unlink ( $dir ); ! 528: ! 529: exec ( "/bin/cp -a '$src' '$dir' 2>&1", $cpytxt, $status ); ! 530: ! 531: if ( $status != 0 ) { ! 532: die ( "src directory copy failed!" ); ! 533: } ! 534: return $dir; ! 535: } ! 536: ! 537: /** ! 538: * Write iPXE config files based on value of given flags ! 539: * ! 540: * iPXE compile options are stored in src/config/*.h . ! 541: * We write out a config file for each set of options. ! 542: * ! 543: * @param string $config_dir directory to write .h files to ! 544: * @param array $flags array of compile options for this build ! 545: * ! 546: * @return void ! 547: */ ! 548: function write_ipxe_config_files ( $config_dir, $flags ) ! 549: { ! 550: global $flag_table; ! 551: ! 552: $cfgsecs = get_flag_cfgsecs (); ! 553: ! 554: foreach ( $cfgsecs as $cfgsec ) { ! 555: ! 556: $fname = $config_dir . "/" . $cfgsec . ".h"; ! 557: ! 558: $fp = fopen ( $fname, "wb" ); ! 559: if ( $fp <= 0 ) { ! 560: die ( "Unable to open $fname file for output!" ); ! 561: } ! 562: ! 563: $ifdef_secname = "CONFIG_" . strtoupper ( $cfgsec ) . "_H"; ! 564: ! 565: fwrite ( $fp, "#ifndef ${ifdef_secname}\n" ); ! 566: fwrite ( $fp, "#define ${ifdef_secname}\n" ); ! 567: fwrite ( $fp, "#include <config/defaults.h>\n" ); ! 568: ! 569: foreach ( $flags as $key => $value ) { ! 570: // When the flag matches this section name, write it out ! 571: if ( $flag_table[$key]["cfgsec"] == $cfgsec ) { ! 572: fwrite ( $fp, pprint_flag ( $key, $value ) . "\n" ); ! 573: } ! 574: } ! 575: fwrite ( $fp, "#endif /* ${ifdef_secname} */\n" ); ! 576: fclose ( $fp ); ! 577: } ! 578: } ! 579: ! 580: /** ! 581: * Output a string to a file ! 582: * ! 583: * Output a given string to a given pathname. The file will be created if ! 584: * necessary, and the string will replace the file's contents in all cases. ! 585: * ! 586: * @param string $fname pathname of file to output string to ! 587: * @param string $ftext text to output to file ! 588: * ! 589: * @return void ! 590: */ ! 591: function write_file_from_string ( $fname, $ftext ) ! 592: { ! 593: $fp = fopen ( $fname, "wb" ); ! 594: if ( ! $fp ) { ! 595: die ( "Unable to open $fname file for output!" ); ! 596: } ! 597: fwrite ( $fp, $ftext ); ! 598: fclose ( $fp ); ! 599: } ! 600: ! 601: /** ! 602: * Delete a file or recursively delete a directory tree ! 603: * ! 604: * @param string $file_or_dir_name name of file or directory to delete ! 605: * @return bool Returns TRUE on success, FALSE on failure ! 606: */ ! 607: function rm_file_or_dir ( $file_or_dir_name ) ! 608: { ! 609: if ( ! file_exists ( $file_or_dir_name ) ) { ! 610: return false; ! 611: } ! 612: ! 613: if ( is_file ( $file_or_dir_name ) || is_link ( $file_or_dir_name ) ) { ! 614: return unlink ( $file_or_dir_name ); ! 615: } ! 616: ! 617: $dir = dir ( $file_or_dir_name ); ! 618: while ( ( $dir_entry = $dir->read () ) !== false ) { ! 619: ! 620: if ( $dir_entry == '.' || $dir_entry == '..') { ! 621: continue; ! 622: } ! 623: rm_file_or_dir ( $file_or_dir_name . '/' . $dir_entry ); ! 624: } ! 625: $dir->close(); ! 626: ! 627: return rmdir ( $file_or_dir_name ); ! 628: } ! 629: ! 630: //// ! 631: // Debugging functions ! 632: //// ! 633: ! 634: /** ! 635: * Emit html code to display given array of compile options (flags) ! 636: * ! 637: * @param array $flags array of compile options for this build ! 638: * ! 639: * @return void ! 640: */ ! 641: function show_flags ( $flags ) ! 642: { ! 643: echo ( "\$flags contains " . count ( $flags ) . " elements:" . "<br>" ); ! 644: ! 645: foreach ( $flags as $key => $flag ) { ! 646: echo ( "\$flags[" . $key . "]=" . "\"$flag\"" . "<br>" ); ! 647: } ! 648: } ! 649: ! 650: /** ! 651: * Emit HTML code to display default array of compile options (flags) ! 652: * ! 653: * $flag_table contains default compile options and properties. This ! 654: * routine outputs HTML code to display all properties of $flag_table. ! 655: * ! 656: * @return void ! 657: */ ! 658: function dump_flag_table () ! 659: { ! 660: global $flag_table; ! 661: ! 662: echo ( "\$flag_table contains " . count ( $flag_table ) . " elements:" . "<br>" ); ! 663: ! 664: foreach ( $flag_table as $key => $props ) { ! 665: print ( "flag_table[" . $key . "] = " . "<br>" ); ! 666: ! 667: foreach ( $props as $key2 => $props2 ) { ! 668: print ( " " . $key2 . " = " . $props2 . "<br>" ); ! 669: } ! 670: } ! 671: } ! 672: ! 673: // Parse src/bin/NIC file ! 674: list ( $nics, $roms ) = parse_nic_file (); ! 675: ! 676: // For emacs: ! 677: // Local variables: ! 678: // c-basic-offset: 4 ! 679: // c-indent-level: 4 ! 680: // tab-width: 4 ! 681: // End: ! 682: ! 683: ?>
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.