[ Index ] |
|
Code source de Drupal 5.3 |
1 <?php 2 // $Id: install.inc,v 1.31.2.2 2007/10/06 22:38:28 drumm Exp $ 3 4 define('SCHEMA_UNINSTALLED', -1); 5 define('SCHEMA_INSTALLED', 0); 6 7 define('REQUIREMENT_INFO', -1); 8 define('REQUIREMENT_OK', 0); 9 define('REQUIREMENT_WARNING', 1); 10 define('REQUIREMENT_ERROR', 2); 11 12 define('FILE_EXIST', 1); 13 define('FILE_READABLE', 2); 14 define('FILE_WRITABLE', 4); 15 define('FILE_EXECUTABLE', 8); 16 define('FILE_NOT_EXIST', 16); 17 define('FILE_NOT_READABLE', 32); 18 define('FILE_NOT_WRITABLE', 64); 19 define('FILE_NOT_EXECUTABLE', 128); 20 21 /** 22 * Initialize the update system by loading all installed module's .install files. 23 */ 24 function drupal_load_updates() { 25 foreach (module_list() as $module) { 26 module_load_install($module); 27 } 28 } 29 30 /** 31 * Returns an array of available schema versions for a module. 32 * 33 * @param $module 34 * A module name. 35 * @return 36 * If the module has updates, an array of available updates. Otherwise, 37 * FALSE. 38 */ 39 function drupal_get_schema_versions($module) { 40 $updates = array(); 41 $functions = get_defined_functions(); 42 foreach ($functions['user'] as $function) { 43 if (strpos($function, $module .'_update_') === 0) { 44 $version = substr($function, strlen($module .'_update_')); 45 if (is_numeric($version)) { 46 $updates[] = $version; 47 } 48 } 49 } 50 if (count($updates) == 0) { 51 return FALSE; 52 } 53 return $updates; 54 } 55 56 /** 57 * Returns the currently installed schema version for a module. 58 * 59 * @param $module 60 * A module name. 61 * @return 62 * The currently installed schema version. 63 */ 64 function drupal_get_installed_schema_version($module, $reset = FALSE) { 65 static $versions = array(); 66 67 if ($reset) { 68 $versions = array(); 69 } 70 71 if (!$versions) { 72 $versions = array(); 73 $result = db_query("SELECT name, schema_version FROM {system} WHERE type = 'module'"); 74 while ($row = db_fetch_object($result)) { 75 $versions[$row->name] = $row->schema_version; 76 } 77 } 78 79 return $versions[$module]; 80 } 81 82 /** 83 * Update the installed version information for a module. 84 * 85 * @param $module 86 * A module name. 87 * @param $version 88 * The new schema version. 89 */ 90 function drupal_set_installed_schema_version($module, $version) { 91 db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module); 92 } 93 94 /** 95 * Loads the profile definition, extracting the profile's defined name. 96 * 97 * @return 98 * The name defined in the profile's _profile_details() hook. 99 */ 100 function drupal_install_profile_name() { 101 global $profile; 102 static $name = NULL; 103 104 if (!isset($name)) { 105 // Load profile details. 106 $function = $profile .'_profile_details'; 107 if (function_exists($function)) { 108 $details = $function(); 109 } 110 $name = isset($details['name']) ? $details['name'] : 'Drupal'; 111 } 112 113 return $name; 114 } 115 116 /** 117 * Auto detect the base_url with PHP predefined variables. 118 * 119 * @param $file 120 * The name of the file calling this function so we can strip it out of 121 * the URI when generating the base_url. 122 * 123 * @return 124 * The auto-detected $base_url that should be configured in settings.php 125 */ 126 function drupal_detect_baseurl($file = 'install.php') { 127 global $profile; 128 $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://'; 129 $host = $_SERVER['SERVER_NAME']; 130 $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'. $_SERVER['SERVER_PORT']); 131 $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']); 132 $dir = str_replace("/$file", '', $uri); 133 134 return "$proto$host$port$dir"; 135 } 136 137 /** 138 * Detect all databases supported by Drupal that are compiled into the current 139 * PHP installation. 140 * 141 * @return 142 * An array of database types compiled into PHP. 143 */ 144 function drupal_detect_database_types() { 145 $databases = array(); 146 147 foreach (array('mysql', 'mysqli', 'pgsql') as $type) { 148 if (file_exists('./includes/install.'. $type .'.inc')) { 149 include_once './includes/install.'. $type .'.inc'; 150 $function = $type .'_is_available'; 151 if ($function()) { 152 $databases[$type] = $type; 153 } 154 } 155 } 156 157 return $databases; 158 } 159 160 /** 161 * Read settings.php into a buffer line by line, changing values specified in 162 * $settings array, then over-writing the old settings.php file. 163 * 164 * @param $settings 165 * An array of settings that need to be updated. 166 */ 167 function drupal_rewrite_settings($settings = array(), $prefix = '') { 168 $settings_file = './'. conf_path() .'/'. $prefix .'settings.php'; 169 170 // Build list of setting names and insert the values into the global namespace. 171 $keys = array(); 172 foreach ($settings as $setting => $data) { 173 $GLOBALS[$setting] = $data['value']; 174 $keys[] = $setting; 175 } 176 177 $buffer = NULL; 178 $first = TRUE; 179 if ($fp = @fopen($settings_file, 'r+')) { 180 // Step line by line through settings.php. 181 while (!feof($fp)) { 182 $line = fgets($fp); 183 if ($first && substr($line, 0, 5) != '<?php') { 184 $buffer = "<?php\n\n"; 185 } 186 $first = FALSE; 187 // Check for constants. 188 if (substr($line, 0, 7) == 'define(') { 189 preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line, $variable); 190 if (in_array($variable[1], $keys)) { 191 $setting = $settings[$variable[1]]; 192 $buffer .= str_replace($variable[2], " '". $setting['value'] ."'", $line); 193 unset($settings[$variable[1]]); 194 unset($settings[$variable[2]]); 195 } 196 else { 197 $buffer .= $line; 198 } 199 } 200 // Check for variables. 201 elseif (substr($line, 0, 1) == '$') { 202 preg_match('/\$([^ ]*) /', $line, $variable); 203 if (in_array($variable[1], $keys)) { 204 // Write new value to settings.php in the following format: 205 // $'setting' = 'value'; // 'comment' 206 $setting = $settings[$variable[1]]; 207 $buffer .= '$'. $variable[1] ." = '". $setting['value'] ."';". ($setting['comment'] ? ' // '. $setting['comment'] ."\n" : "\n"); 208 unset($settings[$variable[1]]); 209 } 210 else { 211 $buffer .= $line; 212 } 213 } 214 else { 215 $buffer .= $line; 216 } 217 } 218 fclose($fp); 219 220 // Add required settings that were missing from settings.php. 221 foreach ($settings as $setting => $data) { 222 if ($data['required']) { 223 $buffer .= "\$$setting = '". $data['value'] ."';\n"; 224 } 225 } 226 227 $fp = fopen($settings_file, 'w'); 228 if ($fp && fwrite($fp, $buffer) === FALSE) { 229 drupal_set_message(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file)), 'error'); 230 } 231 } 232 else { 233 drupal_set_message(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $settings_file)), 'error'); 234 } 235 } 236 237 /** 238 * Get list of all .install files. 239 * 240 * @param $module_list 241 * An array of modules to search for their .install files. 242 */ 243 function drupal_get_install_files($module_list = array()) { 244 $installs = array(); 245 foreach ($module_list as $module) { 246 $installs = array_merge($installs, file_scan_directory('./modules', "^$module.install$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0)); 247 } 248 return $installs; 249 } 250 251 /** 252 * Verify a profile for installation. 253 * 254 * @param profile 255 * Name of profile to verify. 256 * @param locale 257 * Name of locale used (if any). 258 * @return 259 * The list of modules to install. 260 */ 261 function drupal_verify_profile($profile, $locale) { 262 include_once './includes/file.inc'; 263 include_once './includes/common.inc'; 264 265 $profile_file = "./profiles/$profile/$profile.profile"; 266 267 if (!isset($profile) || !file_exists($profile_file)) { 268 install_no_profile_error(); 269 } 270 271 require_once($profile_file); 272 273 // Get a list of modules required by this profile. 274 $function = $profile .'_profile_modules'; 275 $module_list = array_merge(array('system'), $function(), ($locale ? array('locale') : array())); 276 277 // Get a list of modules that exist in Drupal's assorted subdirectories. 278 $present_modules = array(); 279 foreach (drupal_system_listing('\.module$', 'modules', 'name', 0) as $present_module) { 280 $present_modules[] = $present_module->name; 281 } 282 283 // Verify that all of the profile's required modules are present. 284 $missing_modules = array_diff($module_list, $present_modules); 285 if (count($missing_modules)) { 286 foreach ($missing_modules as $module) { 287 drupal_set_message(st('The %module module is required but was not found. Please move it into the <em>modules</em> subdirectory.', array('%module' => $module)), 'error'); 288 } 289 } 290 else { 291 return $module_list; 292 } 293 } 294 295 /** 296 * Install a profile (i.e. a set of modules) from scratch. 297 * The profile must be verified first using drupal_verify_profile(). 298 * 299 * @param profile 300 * The name of the profile to install. 301 * @param module_list 302 * An array of modules to install. 303 */ 304 function drupal_install_profile($profile, $module_list) { 305 // The system module is a special case; we can't bootstrap until it's 306 // installed, so we can't use the normal installation function. 307 $module_list = array_diff($module_list, array('system')); 308 309 $system_path = dirname(drupal_get_filename('module', 'system', NULL)); 310 require_once './' . $system_path . '/system.install'; 311 module_invoke('system', 'install'); 312 $system_versions = drupal_get_schema_versions('system'); 313 $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; 314 db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', 'module', '', 1, 0, 0, %d)", $system_path . '/system.module', 'system', $system_version); 315 316 // Now that we've installed things properly, bootstrap the full Drupal environment 317 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); 318 319 // Install schemas for profile and all its modules. 320 module_rebuild_cache(); 321 drupal_install_modules($module_list); 322 323 // And now, run the profile's install function. 324 $function = $profile .'_install'; 325 if (function_exists($function)) { 326 $function(); 327 } 328 } 329 330 331 /** 332 * Calls the install function and updates the system table for a given list of 333 * modules. 334 * 335 * @param module_list 336 * The modules to install. 337 */ 338 function drupal_install_modules($module_list = array()) { 339 $enable_modules = array(); 340 341 foreach ($module_list as $module) { 342 if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { 343 module_load_install($module); 344 module_invoke($module, 'install'); 345 $versions = drupal_get_schema_versions($module); 346 drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); 347 $enable_modules[] = $module; 348 } 349 } 350 351 module_enable($enable_modules); 352 } 353 354 /** 355 * Calls the uninstall function and updates the system table for a given module. 356 * 357 * @param $module 358 * The module to uninstall. 359 */ 360 function drupal_uninstall_module($module) { 361 module_load_install($module); 362 module_invoke($module, 'uninstall'); 363 drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED); 364 } 365 366 /** 367 * Verify the state of the specified file. 368 * 369 * @param $file 370 * The file to check for. 371 * @param $mask 372 * An optional bitmask created from various FILE_* constants. 373 * @param $type 374 * The type of file. Can be file (default), dir, or link. 375 * @return 376 * TRUE on success or FALSE on failure. A message is set for the latter. 377 */ 378 function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { 379 $return = TRUE; 380 // Check for files that shouldn't be there. 381 if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) { 382 return FALSE; 383 } 384 // Verify that the file is the type of file it is supposed to be. 385 if (isset($type) && file_exists($file)) { 386 $check = 'is_'. $type; 387 if (!function_exists($check) || !$check($file)) { 388 $return = FALSE; 389 } 390 } 391 392 // Verify file permissions. 393 if (isset($mask)) { 394 $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 395 foreach ($masks as $current_mask) { 396 if ($mask & $current_mask) { 397 switch ($current_mask) { 398 case FILE_EXIST: 399 if (!file_exists($file)) { 400 if ($type == 'dir') { 401 drupal_install_mkdir($file, $mask); 402 } 403 if (!file_exists($file)) { 404 $return = FALSE; 405 } 406 } 407 break; 408 case FILE_READABLE: 409 if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) { 410 $return = FALSE; 411 } 412 break; 413 case FILE_WRITABLE: 414 if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) { 415 $return = FALSE; 416 } 417 break; 418 case FILE_EXECUTABLE: 419 if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) { 420 $return = FALSE; 421 } 422 break; 423 case FILE_NOT_READABLE: 424 if (is_readable($file) && !drupal_install_fix_file($file, $mask)) { 425 $return = FALSE; 426 } 427 break; 428 case FILE_NOT_WRITABLE: 429 if (is_writable($file) && !drupal_install_fix_file($file, $mask)) { 430 $return = FALSE; 431 } 432 break; 433 case FILE_NOT_EXECUTABLE: 434 if (is_executable($file) && !drupal_install_fix_file($file, $mask)) { 435 $return = FALSE; 436 } 437 break; 438 } 439 } 440 } 441 } 442 return $return; 443 } 444 445 /** 446 * Create a directory with specified permissions. 447 * 448 * @param file 449 * The name of the directory to create; 450 * @param mask 451 * The permissions of the directory to create. 452 * @param $message 453 * (optional) Whether to output messages. Defaults to TRUE. 454 * 455 * @return 456 * TRUE/FALSE whether or not the directory was successfully created. 457 */ 458 function drupal_install_mkdir($file, $mask, $message = TRUE) { 459 $mod = 0; 460 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 461 foreach ($masks as $m) { 462 if ($mask & $m) { 463 switch ($m) { 464 case FILE_READABLE: 465 $mod += 444; 466 break; 467 case FILE_WRITABLE: 468 $mod += 222; 469 break; 470 case FILE_EXECUTABLE: 471 $mod += 111; 472 break; 473 } 474 } 475 } 476 477 if (@mkdir($file, intval("0$mod", 8))) { 478 return TRUE; 479 } 480 else { 481 return FALSE; 482 } 483 } 484 485 /** 486 * Attempt to fix file permissions. 487 * 488 * The general approach here is that, because we do not know the security 489 * setup of the webserver, we apply our permission changes to all three 490 * digits of the file permission (i.e. user, group and all). 491 * 492 * To ensure that the values behave as expected (and numbers don't carry 493 * from one digit to the next) we do the calculation on the octal value 494 * using bitwise operations. This lets us remove, for example, 0222 from 495 * 0700 and get the correct value of 0500. 496 * 497 * @param $file 498 * The name of the file with permissions to fix. 499 * @param $mask 500 * The desired permissions for the file. 501 * @param $message 502 * (optional) Whether to output messages. Defaults to TRUE. 503 * 504 * @return 505 * TRUE/FALSE whether or not we were able to fix the file's permissions. 506 */ 507 function drupal_install_fix_file($file, $mask, $message = TRUE) { 508 $mod = fileperms($file) & 0777; 509 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 510 511 // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings 512 // can theoretically be 0400, 0200, and 0100 respectively, but to be safe 513 // we set all three access types in case the administrator intends to 514 // change the owner of settings.php after installation. 515 foreach ($masks as $m) { 516 if ($mask & $m) { 517 switch ($m) { 518 case FILE_READABLE: 519 if (!is_readable($file)) { 520 $mod |= 0444; 521 } 522 break; 523 case FILE_WRITABLE: 524 if (!is_writable($file)) { 525 $mod |= 0222; 526 } 527 break; 528 case FILE_EXECUTABLE: 529 if (!is_executable($file)) { 530 $mod |= 0111; 531 } 532 break; 533 case FILE_NOT_READABLE: 534 if (is_readable($file)) { 535 $mod &= ~0444; 536 } 537 break; 538 case FILE_NOT_WRITABLE: 539 if (is_writable($file)) { 540 $mod &= ~0222; 541 } 542 break; 543 case FILE_NOT_EXECUTABLE: 544 if (is_executable($file)) { 545 $mod &= ~0111; 546 } 547 break; 548 } 549 } 550 } 551 552 // chmod() will work if the web server is running as owner of the file. 553 // If PHP safe_mode is enabled the currently executing script must also 554 // have the same owner. 555 if (@chmod($file, $mod)) { 556 return TRUE; 557 } 558 else { 559 return FALSE; 560 } 561 } 562 563 564 /** 565 * Send the user to a different installer page. This issues an on-site HTTP 566 * redirect. Messages (and errors) are erased. 567 * 568 * @param $path 569 * An installer path. 570 */ 571 function install_goto($path) { 572 global $base_url; 573 header('Location: '. $base_url . '/' . $path); 574 header('Cache-Control: no-cache'); // Not a permanent redirect. 575 exit(); 576 } 577 578 /** 579 * Hardcoded function for doing the equivalent of theme('placeholder') 580 * when the theme system is not available. 581 */ 582 function st($string, $args = array()) { 583 static $locale_strings = NULL; 584 global $profile, $install_locale; 585 586 if (!isset($locale_strings)) { 587 $locale_strings = array(); 588 $filename = './profiles/' . $profile . '/' . $install_locale . '.po'; 589 if (file_exists($filename)) { 590 require_once './includes/locale.inc'; 591 $file = (object) array('filepath' => $filename); 592 _locale_import_read_po('mem-store', $file); 593 $locale_strings = _locale_import_one_string('mem-report'); 594 } 595 } 596 597 require_once './includes/theme.inc'; 598 $GLOBALS['theme'] = 'theme'; 599 // Transform arguments before inserting them 600 foreach ($args as $key => $value) { 601 switch ($key[0]) { 602 // Escaped only 603 case '@': 604 $args[$key] = check_plain($value); 605 break; 606 // Escaped and placeholder 607 case '%': 608 default: 609 $args[$key] = '<em>'. check_plain($value) .'</em>'; 610 break; 611 // Pass-through 612 case '!': 613 } 614 } 615 return strtr((!empty($locale_strings[$string]) ? $locale_strings[$string] : $string), $args); 616 } 617 618 /** 619 * Converts a set of tables to UTF-8 encoding. 620 * 621 * This update is designed to be re-usable by contrib modules and is 622 * used by system_update_169(). 623 */ 624 function _system_update_utf8($tables) { 625 // Are we starting this update for the first time? 626 if (!isset($_SESSION['update_utf8'])) { 627 switch ($GLOBALS['db_type']) { 628 // Only for MySQL 4.1+ 629 case 'mysqli': 630 break; 631 case 'mysql': 632 if (version_compare(mysql_get_server_info($GLOBALS['active_db']), '4.1.0', '<')) { 633 return array(); 634 } 635 break; 636 case 'pgsql': 637 return array(); 638 } 639 640 // See if database uses UTF-8 already 641 global $db_url; 642 $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url); 643 $db_name = substr($url['path'], 1); 644 $result = db_fetch_array(db_query('SHOW CREATE DATABASE `%s`', $db_name)); 645 if (preg_match('/utf8/i', array_pop($result))) { 646 return array(); 647 } 648 649 // Make list of tables to convert 650 $_SESSION['update_utf8'] = $tables; 651 // Keep track of total for progress bar 652 $_SESSION['update_utf8_total'] = count($tables); 653 } 654 655 // Fetch remaining tables list and convert next table 656 $list = &$_SESSION['update_utf8']; 657 658 $ret = update_convert_table_utf8(array_shift($list)); 659 660 // Are we done? 661 if (count($list) == 0) { 662 unset($_SESSION['update_utf8']); 663 unset($_SESSION['update_utf8_total']); 664 return $ret; 665 } 666 667 // Progress percentage 668 $ret['#finished'] = 1 - (count($list) / $_SESSION['update_utf8_total']); 669 return $ret; 670 } 671 672 /** 673 * Check a profile's requirements. 674 * 675 * @param profile 676 * Name of profile to check. 677 */ 678 function drupal_check_profile($profile) { 679 include_once './includes/file.inc'; 680 681 $profile_file = "./profiles/$profile/$profile.profile"; 682 683 if (!isset($profile) || !file_exists($profile_file)) { 684 install_no_profile_error(); 685 } 686 687 require_once($profile_file); 688 689 // Get a list of modules required by this profile. 690 $function = $profile .'_profile_modules'; 691 $module_list = array_unique(array_merge(array('system'), $function())); 692 693 // Get a list of all .install files. 694 $installs = drupal_get_install_files($module_list); 695 696 // Collect requirement testing results 697 $requirements = array(); 698 foreach ($installs as $install) { 699 require_once $install->filename; 700 if (module_hook($install->name, 'requirements')) { 701 $requirements = array_merge($requirements, module_invoke($install->name, 'requirements', 'install')); 702 } 703 } 704 return $requirements; 705 } 706 707 /** 708 * Extract highest severity from requirements array. 709 */ 710 function drupal_requirements_severity(&$requirements) { 711 $severity = REQUIREMENT_OK; 712 foreach ($requirements as $requirement) { 713 if (isset($requirement['severity'])) { 714 $severity = max($severity, $requirement['severity']); 715 } 716 } 717 return $severity; 718 } 719 720 /** 721 * Check a module's requirements. 722 */ 723 function drupal_check_module($module) { 724 // Include install file 725 $install = drupal_get_install_files(array($module)); 726 if (isset($install[$module])) { 727 require_once $install[$module]->filename; 728 729 // Check requirements 730 $requirements = module_invoke($module, 'requirements', 'install'); 731 if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) { 732 // Print any error messages 733 foreach ($requirements as $requirement) { 734 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { 735 drupal_set_message($requirement['description'] .' ('. t('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')', 'error'); 736 } 737 } 738 return FALSE; 739 } 740 } 741 return TRUE; 742 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 16:20:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |