Line # | Frequency | Source Line |
1 | | <?php |
2 | | // $Id: install.inc,v 1.58 2008/02/12 13:45:16 dries Exp $ |
3 | |
|
4 | 1 | define('SCHEMA_UNINSTALLED', -1); |
5 | 1 | define('SCHEMA_INSTALLED', 0); |
6 | |
|
7 | 1 | define('REQUIREMENT_INFO', -1); |
8 | 1 | define('REQUIREMENT_OK', 0); |
9 | 1 | define('REQUIREMENT_WARNING', 1); |
10 | 1 | define('REQUIREMENT_ERROR', 2); |
11 | |
|
12 | 1 | define('FILE_EXIST', 1); |
13 | 1 | define('FILE_READABLE', 2); |
14 | 1 | define('FILE_WRITABLE', 4); |
15 | 1 | define('FILE_EXECUTABLE', 8); |
16 | 1 | define('FILE_NOT_EXIST', 16); |
17 | 1 | define('FILE_NOT_READABLE', 32); |
18 | 1 | define('FILE_NOT_WRITABLE', 64); |
19 | 1 | 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 (drupal_get_installed_schema_version(NULL, FALSE, TRUE) as $module => $schema_version) { |
26 | | if ($schema_version > -1) { |
27 | | module_load_install($module); |
28 | | } |
29 | | } |
30 | | } |
31 | |
|
32 | | /** |
33 | | * Returns an array of available schema versions for a module. |
34 | | * |
35 | | * @param $module |
36 | | * A module name. |
37 | | * @return |
38 | | * If the module has updates, an array of available updates. Otherwise, |
39 | | * FALSE. |
40 | | */ |
41 | | function drupal_get_schema_versions($module) { |
42 | | $updates = array(); |
43 | 1 | $functions = get_defined_functions(); |
44 | 1 | foreach ($functions['user'] as $function) { |
45 | 1 | if (strpos($function, $module .'_update_') === 0) { |
46 | 1 | $version = substr($function, strlen($module .'_update_')); |
47 | 1 | if (is_numeric($version)) { |
48 | 1 | $updates[] = $version; |
49 | | } |
50 | | } |
51 | | } |
52 | 1 | if (count($updates) == 0) { |
53 | 1 | return FALSE; |
54 | | } |
55 | 1 | 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 | 1 | if ($reset) { |
75 | | $versions = array(); |
76 | | } |
77 | |
|
78 | 1 | if (!$versions) { |
79 | | $versions = array(); |
80 | 1 | $result = db_query("SELECT name, schema_version FROM {system} WHERE type = '%s'", 'module'); |
81 | 1 | while ($row = db_fetch_object($result)) { |
82 | 1 | $versions[$row->name] = $row->schema_version; |
83 | | } |
84 | | } |
85 | |
|
86 | 1 | 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 | 1 | 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 | 1 | $profile_file = "./profiles/$profile/$profile.profile"; |
274 | |
|
275 | 1 | 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 | 1 | $function = $profile .'_profile_modules'; |
283 | 1 | $module_list = array_merge(drupal_required_modules(), $function(), ($locale != 'en' ? array('locale') : array())); |
284 | |
|
285 | | // Get a list of modules that exist in Drupal's assorted subdirectories. |
286 | | $present_modules = array(); |
287 | 1 | foreach (drupal_system_listing('\.module$', 'modules', 'name', 0) as $present_module) { |
288 | 1 | $present_modules[] = $present_module->name; |
289 | | } |
290 | |
|
291 | | // Verify that all of the profile's required modules are present. |
292 | 1 | $missing_modules = array_diff($module_list, $present_modules); |
293 | 1 | 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 | 1 | 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 | 1 | $files = module_rebuild_cache(); |
312 | 1 | $module_list = array_flip(array_values($module_list)); |
313 | | do { |
314 | 1 | $moved = FALSE; |
315 | 1 | foreach ($module_list as $module => $weight) { |
316 | 1 | $file = $files[$module]; |
317 | 1 | if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) { |
318 | 1 | 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 | 1 | asort($module_list); |
328 | 1 | $module_list = array_keys($module_list); |
329 | 1 | array_filter($module_list, '_drupal_install_module'); |
330 | 1 | 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 | 1 | if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { |
342 | 1 | module_load_install($module); |
343 | 1 | module_invoke($module, 'install'); |
344 | 1 | $versions = drupal_get_schema_versions($module); |
345 | 1 | drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); |
346 | 1 | 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 | 1 | $system_path = dirname(drupal_get_filename('module', 'system', NULL)); |
358 | | require_once './'. $system_path .'/system.install'; |
359 | 1 | module_invoke('system', 'install'); |
360 | 1 | $system_versions = drupal_get_schema_versions('system'); |
361 | 1 | $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; |
362 | 1 | 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 | 1 | drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); |
365 | 1 | 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 | 1 | static $locale_strings = NULL; |
629 | 1 | global $profile, $install_locale; |
630 | |
|
631 | 1 | if (!isset($locale_strings)) { |
632 | | $locale_strings = array(); |
633 | 1 | $filename = './profiles/'. $profile .'/translations/'. $install_locale .'.po'; |
634 | 1 | 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 | 1 | 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 | 1 | 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 | | } |