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