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