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 | } |
---|