blob: a4d594059215c62c99fdb45c1cbb6b4ca42a9234 [file] [log] [blame]
Nico Huberee52fbc2023-06-24 11:52:57 +00001<?php
2/*
3 * SimpleID
4 *
5 * Copyright (C) Kelvin Mo 2009
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * $Id$
22 */
23
24/**
25 * SimpleID upgrade script.
26 *
27 * This script performs various upgrades to SimpleID's storage backend, which
28 * are required for different versions of SimpleID.
29 *
30 * @package simpleid
31 * @since 0.7
32 * @filesource
33 */
34
35/**
36 * Access control for this script.
37 *
38 * If you are upgrading your SimpleID installation using the upgrade.php script,
39 * and you are not logged in as an administrator, you will need to modify the access
40 * check statement below.
41 *
42 * Change the TRUE to a FALSE to disable the access
43 * check. After finishing the upgrade, be sure to open this file again
44 * and change the FALSE back to a TRUE.
45 *
46 * @global bool $upgrade_access_check
47 */
48$upgrade_access_check = TRUE;
49
50/* ----- Do not modify anything following this line ------------------------- */
51
52include_once "version.inc.php";
53include_once "locale.inc.php";
54if (file_exists("config.php")) {
55 include_once "config.php";
56} elseif (file_exists("config.inc")) {
57 include_once "config.inc";
58 define('UPGRADE_LEGACY_CONFIG_INC', TRUE);
59} else {
60 die(t('No configuration file found. See the <a href="!url">manual</a> for instructions on how to set up a configuration file.', array('!url' => 'http://simpleid.org/docs/1/installing/')));
61}
62include_once "config.default.php";
63include_once "log.inc.php";
64include_once "common.inc.php";
65include_once "simpleweb.inc.php";
66include_once "openid.inc.php";
67include_once "user.inc.php";
68include_once "cache.inc.php";
69include_once SIMPLEID_STORE . ".store.php";
70include "lib/xtemplate.class.php";
71
72define('CACHE_DIR', SIMPLEID_CACHE_DIR);
73
74define('PRE_0_7_0_VERSION', '0.6.0 or earlier');
75
76/**
77 * This variable holds the upgrade functions for each version of SimpleID
78 *
79 * @global array $upgrade_functions
80 */
81$upgrade_functions = array(
82 '0.9.0' => array('upgrade_config_inc_to_php', 'upgrade_delete_token'),
83 '0.7.0' => array('upgrade_rp_to_store', 'upgrade_token_to_store')
84);
85
86
87/**
88 * This variable holds an instance of the XTemplate engine.
89 *
90 * @global object $xtpl
91 */
92$xtpl = NULL;
93
94/**
95 * This variable holds the combined $_GET and $_POST superglobal arrays.
96 *
97 * @global array $GETPOST
98 */
99$GETPOST = array_merge($_GET, $_POST);
100
101upgrade_start();
102
103/**
104 * Entry point for SimpleID upgrade script.
105 *
106 * @see user_init()
107 */
108function upgrade_start() {
109 global $xtpl, $GETPOST;
110
111 locale_init(SIMPLEID_LOCALE);
112
113 $xtpl = new XTemplate('html/template.xtpl');
114 $xtpl->assign('version', SIMPLEID_VERSION);
115 $xtpl->assign('base_path', get_base_path());
116 $xtpl->assign('css', '@import url(' . get_base_path() . 'html/upgrade.css);');
117 $xtpl->assign('footer_doc', t('Documentation'));
118 $xtpl->assign('footer_support', t('Support'));
119
120 if (!is_dir(SIMPLEID_IDENTITIES_DIR)) {
121 indirect_fatal_error(t('Identities directory not found. See the <a href="!url">manual</a> for instructions on how to set up SimpleID.', array('!url' => 'http://simpleid.org/docs/1/installing/')));
122 }
123
124 if (!is_dir(SIMPLEID_CACHE_DIR) || !is_writeable(SIMPLEID_CACHE_DIR)) {
125 indirect_fatal_error(t('Cache directory not found or not writeable. See the <a href="!url">manual</a> for instructions on how to set up SimpleID.', array('!url' => 'http://simpleid.org/docs/1/installing/')));
126 }
127
128 if (!is_dir(SIMPLEID_STORE_DIR) || !is_writeable(SIMPLEID_STORE_DIR)) {
129 indirect_fatal_error(t('Store directory not found or not writeable. See the <a href="!url">manual</a> for instructions on how to set up SimpleID.', array('!url' => 'http://simpleid.org/docs/1/installing/')));
130 }
131
132 if ((@ini_get('register_globals') === 1) || (@ini_get('register_globals') === '1') || (strtolower(@ini_get('register_globals')) == 'on')) {
133 indirect_fatal_error(t('register_globals is enabled in PHP configuration, which is not supported by SimpleID. See the <a href="!url">manual</a> for further information.', array('!url' => 'http://simpleid.org/docs/1/system-requirements/')));
134 }
135
136 if (!bignum_loaded()) {
137 log_fatal('gmp/bcmath PHP extension not loaded.');
138 indirect_fatal_error(t('One or more required PHP extensions (%extension) is not loaded. See the <a href="!url">manual</a> for further information on system requirements.', array('%extension' => 'gmp/bcmath', '!url' => 'http://simpleid.org/docs/1/system-requirements/')));
139 }
140 if (!function_exists('preg_match')) {
141 log_fatal('pcre PHP extension not loaded.');
142 indirect_fatal_error(t('One or more required PHP extensions (%extension) is not loaded. See the <a href="!url">manual</a> for further information on system requirements.', array('%extension' => 'pcre', '!url' => 'http://simpleid.org/docs/1/system-requirements/')));
143 }
144 if (!function_exists('session_start')) {
145 log_fatal('session PHP extension not loaded.');
146 indirect_fatal_error(t('One or more required PHP extensions (%extension) is not loaded. See the <a href="!url">manual</a> for further information on system requirements.', array('%extension' => 'session', '!url' => 'http://simpleid.org/docs/1/system-requirements/')));
147 }
148 if (!function_exists('xml_parser_create_ns')) {
149 log_fatal('xml PHP extension not loaded.');
150 indirect_fatal_error(t('One or more required PHP extensions (%extension) is not loaded. See the <a href="!url">manual</a> for further information on system requirements.', array('%extension' => 'xml', '!url' => 'http://simpleid.org/docs/1/system-requirements/')));
151 }
152 if (!function_exists('hash')) {
153 log_fatal('hash PHP extension not loaded.');
154 indirect_fatal_error(t('One or more required PHP extensions (%extension) is not loaded. See the <a href="!url">manual</a> for further information on system requirements.', array('%extension' => 'hash', '!url' => 'http://simpleid.org/docs/1/system-requirements/')));
155 }
156 if (is_numeric(@ini_get('suhosin.get.max_value_length')) && (@ini_get('suhosin.get.max_value_length') < 1024)) {
157 log_fatal('suhosin.get.max_value_length < 1024');
158 indirect_fatal_error(t('suhosin.get.max_value_length is less than 1024, which will lead to problems. See the <a href="!url">manual</a> for further information on system requirements.', array('!url' => 'http://simpleid.org/docs/1/system-requirements/')));
159 }
160
161 $q = (isset($GETPOST['q'])) ? $GETPOST['q'] : '';
162 $q = explode('/', $q);
163
164 extension_init();
165 user_init(NULL);
166 upgrade_user_init();
167
168 $routes = array(
169 'upgrade-selection' => 'upgrade_selection',
170 'upgrade-apply' => 'upgrade_apply',
171 '.*' => 'upgrade_info'
172 );
173
174 simpleweb_run($routes, implode('/', $q));
175}
176
177/**
178 * Displays the upgrade info page.
179 */
180function upgrade_info() {
181 global $xtpl;
182
183 $xtpl->assign('token', get_form_token('upgrade_info'));
184
185 $xtpl->assign('intro', t('Use this script to update your installation whenever you upgrade to a new version of SimpleID.'));
186 $xtpl->assign('simpleid_docs', t('For more detailed information, see the <a href="!url">SimpleID documentation</a>.', array('!url' => 'http://simpleid.org/docs/1/upgrading/')));
187 $xtpl->assign('step1', t('<strong>Back up your installation</strong>. This process will change various files within your SimpleID installation and in case of emergency you may need to revert to a backup.'));
188 $xtpl->assign('step2', t('Install your new files in the appropriate location, as described in the <a href="!url">SimpleID documentation</a>.', array('!url' => 'http://simpleid.org/docs/1/installing/')));
189 $xtpl->assign('click_continue', t('When you have performed the steps above, click <strong>Continue</strong>.'));
190 $xtpl->assign('continue_button', t('Continue'));
191
192 $xtpl->parse('main.upgrade_info');
193
194 $xtpl->assign('title', t('Upgrade'));
195 $xtpl->parse('main');
196
197 $xtpl->out('main');
198}
199
200/**
201 * Detects the current installed version of SimpleID, selects the individual upgrade
202 * functions applicable to this upgrade and displays the upgrade
203 * selection page.
204 */
205function upgrade_selection() {
206 global $xtpl, $upgrade_access_check;
207
208 cache_expire(array('upgrade' => 0));
209
210 if (!validate_form_token($_POST['tk'], 'upgrade_info')) {
211 set_message(t('SimpleID detected a potential security attack. Please try again.'));
212 upgrade_info();
213 return;
214 }
215
216 $functions = upgrade_get_functions();
217
218 if (count($functions) == 0) {
219 if (!$upgrade_access_check) {
220 $xtpl->assign('edit_upgrade_php', t('Remember to edit upgrade.php to check <code>$upgrade_access_check</code> back to <code>FALSE</code>.'));
221 $xtpl->parse('main.selection.selection_complete.upgrade_access_check');
222 }
223
224 $xtpl->assign('script_complete', t('Your SimpleID installation is up-to-date. This script is complete.'));
225
226 $xtpl->parse('main.upgrade_selection.selection_complete');
227 } else {
228 $handle = random_id();
229 cache_set('upgrade', $handle, $functions);
230
231 $xtpl->assign('handle', $handle);
232 $xtpl->assign('token', get_form_token('upgrade_selection'));
233
234 $xtpl->assign('click_continue', t('Click <strong>Continue</strong> to proceed with the upgrade.'));
235 $xtpl->assign('continue_button', t('Continue'));
236
237 $xtpl->parse('main.upgrade_selection.selection_continue');
238 }
239
240 $xtpl->assign('original_version', upgrade_get_version());
241 $xtpl->assign('this_version', SIMPLEID_VERSION);
242
243 $xtpl->assign('version_detected', t('The version of SimpleID you are updating from has been automatically detected.'));
244 $xtpl->assign('original_version_label', t('Original version'));
245 $xtpl->assign('this_version_label', t('Upgrade version'));
246
247 $xtpl->parse('main.upgrade_selection');
248
249 $xtpl->assign('title', t('Upgrade'));
250 $xtpl->parse('main');
251
252 $xtpl->out('main');
253}
254
255/**
256 * Applies the upgrade.
257 */
258function upgrade_apply() {
259 global $xtpl, $upgrade_access_check;
260
261 if (!validate_form_token($_POST['tk'], 'upgrade_selection')) {
262 set_message(t('SimpleID detected a potential security attack. Please try again.'));
263 upgrade_selection();
264 return;
265 }
266
267 $results = '';
268 $functions = cache_get('upgrade', $_POST['handle']);
269
270 foreach ($functions as $function) {
271 $results .= call_user_func($function);
272 }
273
274 if (!$upgrade_access_check) {
275 $xtpl->assign('edit_upgrade_php', t('Remember to edit upgrade.php to check <code>$upgrade_access_check</code> back to <code>TRUE</code>.'));
276 $xtpl->parse('main.upgrade_results.upgrade_access_check');
277 }
278 $xtpl->assign('results', $results);
279
280 $xtpl->assign('upgrade_complete', t('Your SimpleID installation has been upgraded. Please check the results below for any errors.'));
281
282 $xtpl->parse('main.upgrade_results');
283
284 cache_expire(array('upgrade' => 0));
285
286 $xtpl->assign('title', t('Upgrade'));
287 $xtpl->parse('main');
288
289 $xtpl->out('main');
290}
291
292/**
293 * Detects the current installed version of SimpleID
294 *
295 * The current installed version of SimpleID is taken from the {@link store_get() version}
296 * application setting. This setting is only available for versions 0.7 or later, so
297 * if it is absent we can assume it's prior to version 0.7.
298 *
299 * @return string the detected version, or the string '0.6.0 or earlier'
300 */
301function upgrade_get_version() {
302 return store_get('version', '0.6.0 or earlier');
303}
304
305/**
306 * Sets the current version of SimpleID.
307 *
308 * This function sets the version application setting via {@link store_get()}.
309 * A specific version can be specified, or it can be taken from {@link SIMPLEID_VERSION}.
310 *
311 * @param string $version the version to set
312 */
313function upgrade_set_version($version = NULL) {
314 if ($version == NULL) $version = SIMPLEID_VERSION;
315 store_set('version', $version);
316}
317
318/**
319 * Selects the upgrade functions applicable for this upgrade.
320 *
321 * The upgrade functions are specified by the {@link $upgrade_functions}
322 * variable. This variable is an associative array containing version numbers
323 * as keys and an array of upgrade function names as values. This function
324 * merges all the upgrade function names of the version between the current
325 * installed version and the upgraded version.
326 *
327 * @param string $version the version of SimpleID to upgrade from, calls
328 * {@link upgrade_get_version()} if not specified
329 * @return array an array of strings, containing the list of upgrade functions
330 * to call. The functions should be called in the same order as they appear
331 * in this array
332 *
333 */
334function upgrade_get_functions($version = NULL) {
335 global $upgrade_functions;
336
337 if ($version == NULL) $version = upgrade_get_version();
338 $functions = array();
339
340 uksort($upgrade_functions, '_upgrade_version_reverse_sort');
341
342 foreach ($upgrade_functions as $upgrade_version => $upgrades) {
343 if (version_compare($version, $upgrade_version, '<')) {
344 $functions = array_merge($functions, $upgrades);
345 }
346 }
347
348 if (version_compare($version, SIMPLEID_VERSION, '<')) $functions[] = 'upgrade_set_version';
349
350 return $functions;
351}
352
353/**
354 * Callback function for uksort() to reverse sort version numbers.
355 *
356 * @param string $a
357 * @param string $b
358 * @return int
359 */
360function _upgrade_version_reverse_sort($a, $b) {
361 return -version_compare($a, $b);
362}
363
364/**
365 * Determines whether the current user has permission to run this script.
366 *
367 * A user has permission to run this script if:
368 *
369 * - administrator=1 appears in the user's identity file; or
370 * - {@link $upgrade_access_check} is false
371 *
372 * If the user does not have permission, {@link upgade_access_denied()} is called
373 */
374function upgrade_user_init() {
375 global $user, $upgrade_access_check;
376
377 if ($upgrade_access_check) {
378 if (($user == NULL) || ($user['administrator'] != 1)) upgrade_access_denied();
379 }
380}
381
382/**
383 * Displays a page notifying the user that he or she does not have permission to
384 * run the upgrade script.
385 */
386function upgrade_access_denied() {
387 global $xtpl;
388
389 $xtpl->assign('login_required', t('Access denied. You are not authorised to access this page. Please <a href="index.php?q=login">log in</a> as an administrator (a user whose identity file includes the line <code>administrator=1</code>).'));
390 $xtpl->assign('edit_upgrade_php', t('If you cannot log in, you will have to edit <code>upgrade.php</code> to bypass this access check. To do this:'));
391 $xtpl->assign('edit_upgrade_php1', t('With a text editor find the upgrade.php file.'));
392 $xtpl->assign('edit_upgrade_php2', t('There is a line inside your upgrade.php file that says <code>$upgrade_access_check = TRUE;</code>. Change it to <code>$upgrade_access_check = FALSE;</code>.'));
393 $xtpl->assign('edit_upgrade_php3', t('As soon as the upgrade.php script is done, you must change the file back to its original form with <code>$upgrade_access_check = TRUE;</code>.'));
394 $xtpl->assign('edit_upgrade_php4', t('To avoid having this problem in future, remember to log in to SimpleID as an administrator before you run this script.'));
395 $xtpl->assign('simpleid_docs', t('For more detailed information, see the <a href="!url">SimpleID documentation</a>.', array('!url' => 'http://simpleid.org/docs/1/upgrading/')));
396
397 $xtpl->parse('main.upgrade_access_denied');
398
399 $xtpl->assign('title', t('Access Denied'));
400 $xtpl->parse('main');
401
402 $xtpl->out('main');
403 exit;
404}
405
406/* ------------------------------------------------------------------------------------------------------- */
407
408/**
409 * Moves the user's site preferences from the cache to the store.
410 *
411 * @since 0.7
412 */
413function upgrade_rp_to_store() {
414 $dir = opendir(SIMPLEID_IDENTITIES_DIR);
415
416 while (($file = readdir($dir)) !== false) {
417 $filename = SIMPLEID_IDENTITIES_DIR . '/' . $file;
418
419 if ((filetype($filename) != "file") || (!preg_match('/^(.+)\.identity$/', $file, $matches))) continue;
420
421 $uid = $matches[1];
422
423 $user = user_load($uid);
424 $rp = cache_get('rp', $uid);
425 if ($rp != NULL) {
426 $user['rp'] = $rp;
427 user_save($user);
428 cache_delete('rp', $uid);
429 }
430 }
431}
432
433/**
434 * Moves the site token from the cache to the store.
435 *
436 * @since 0.7
437 */
438function upgrade_token_to_store() {
439 $site_token = cache_get('token', SIMPLEID_BASE_URL);
440
441 if ($site_token != NULL) {
442 store_set('site-token', $site_token);
443 cache_delete('token', SIMPLEID_BASE_URL);
444 }
445}
446
447/**
448 * Checks that config.inc has been renamed to config.php
449 *
450 * @since 0.9
451 */
452function upgrade_config_inc_to_php() {
453 if (defined('UPGRADE_LEGACY_CONFIG_INC')) {
454 return '<p>You will need to rename <code>config.inc</code> to <code>config.php</code>.</p>';
455 }
456}
457
458/**
459 * Deletes the site-token setting for a more secure version
460 *
461 * @since 0.9
462 */
463function upgrade_delete_token() {
464 store_del('site-token');
465}
466?>