commit | author | age
|
d48470
|
1 |
#!/usr/bin/env php |
fee8c6
|
2 |
<?php |
e6bb83
|
3 |
/* |
T |
4 |
+-----------------------------------------------------------------------+ |
|
5 |
| bin/update.sh | |
|
6 |
| | |
|
7 |
| This file is part of the Roundcube Webmail client | |
a612c5
|
8 |
| Copyright (C) 2010-2015, The Roundcube Dev Team | |
7fe381
|
9 |
| | |
T |
10 |
| Licensed under the GNU General Public License version 3 or | |
|
11 |
| any later version with exceptions for skins & plugins. | |
|
12 |
| See the README file for a full license statement. | |
e6bb83
|
13 |
| | |
T |
14 |
| PURPOSE: | |
|
15 |
| Check local configuration and database schema after upgrading | |
|
16 |
| to a new version | |
|
17 |
+-----------------------------------------------------------------------+ |
|
18 |
| Author: Thomas Bruederli <roundcube@gmail.com> | |
|
19 |
+-----------------------------------------------------------------------+ |
|
20 |
*/ |
|
21 |
|
0ea079
|
22 |
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' ); |
fee8c6
|
23 |
|
e6bb83
|
24 |
require_once INSTALL_PATH . 'program/include/clisetup.php'; |
T |
25 |
|
|
26 |
// get arguments |
447fc6
|
27 |
$opts = rcube_utils::get_opt(array('v' => 'version', 'y' => 'accept')); |
e6bb83
|
28 |
|
T |
29 |
// ask user if no version is specified |
|
30 |
if (!$opts['version']) { |
|
31 |
echo "What version are you upgrading from? Type '?' if you don't know.\n"; |
|
32 |
if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z-]*$/', $input)) |
|
33 |
$opts['version'] = $input; |
63cf4f
|
34 |
else |
AM |
35 |
$opts['version'] = RCMAIL_VERSION; |
e6bb83
|
36 |
} |
T |
37 |
|
eea11e
|
38 |
$RCI = rcmail_install::get_instance(); |
fee8c6
|
39 |
$RCI->load_config(); |
T |
40 |
|
|
41 |
if ($RCI->configured) { |
2491c6
|
42 |
$success = true; |
461a30
|
43 |
|
9bacb2
|
44 |
if (($messages = $RCI->check_config()) || $RCI->legacy_config) { |
2491c6
|
45 |
$success = false; |
fee8c6
|
46 |
$err = 0; |
T |
47 |
|
|
48 |
// list old/replaced config options |
|
49 |
if (is_array($messages['replaced'])) { |
|
50 |
echo "WARNING: Replaced config options:\n"; |
|
51 |
echo "(These config options have been replaced or renamed)\n"; |
|
52 |
|
|
53 |
foreach ($messages['replaced'] as $msg) { |
cbffc2
|
54 |
echo "- '" . $msg['prop'] . "' was replaced by '" . $msg['replacement'] . "'\n"; |
fee8c6
|
55 |
$err++; |
T |
56 |
} |
|
57 |
echo "\n"; |
|
58 |
} |
|
59 |
|
|
60 |
// list obsolete config options (just a notice) |
|
61 |
if (is_array($messages['obsolete'])) { |
|
62 |
echo "NOTICE: Obsolete config options:\n"; |
|
63 |
echo "(You still have some obsolete or inexistent properties set. This isn't a problem but should be noticed)\n"; |
|
64 |
|
|
65 |
foreach ($messages['obsolete'] as $msg) { |
cbffc2
|
66 |
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n"; |
fee8c6
|
67 |
$err++; |
T |
68 |
} |
|
69 |
echo "\n"; |
|
70 |
} |
|
71 |
|
9bacb2
|
72 |
if (!$err && $RCI->legacy_config) { |
TB |
73 |
echo "WARNING: Your configuration needs to be migrated!\n"; |
|
74 |
echo "We changed the configuration files structure and your two config files main.inc.php and db.inc.php have to be merged into one single file.\n"; |
|
75 |
$err++; |
|
76 |
} |
|
77 |
|
fee8c6
|
78 |
// ask user to update config files |
T |
79 |
if ($err) { |
447fc6
|
80 |
if (!$opts['accept']) { |
TB |
81 |
echo "Do you want me to fix your local configuration? (y/N)\n"; |
|
82 |
$input = trim(fgets(STDIN)); |
|
83 |
} |
fee8c6
|
84 |
|
T |
85 |
// positive: let's merge the local config with the defaults |
447fc6
|
86 |
if ($opts['accept'] || strtolower($input) == 'y') { |
9bacb2
|
87 |
$error = $written = false; |
461a30
|
88 |
|
fee8c6
|
89 |
// backup current config |
461a30
|
90 |
echo ". backing up the current config file(s)...\n"; |
AM |
91 |
|
|
92 |
foreach (array('config', 'main', 'db') as $file) { |
9bacb2
|
93 |
if (file_exists(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php')) { |
461a30
|
94 |
if (!copy(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php', RCMAIL_CONFIG_DIR . '/' . $file . '.old.php')) { |
AM |
95 |
$error = true; |
|
96 |
} |
|
97 |
} |
fee8c6
|
98 |
} |
461a30
|
99 |
|
AM |
100 |
if (!$error) { |
|
101 |
$RCI->merge_config(); |
|
102 |
echo ". writing " . RCMAIL_CONFIG_DIR . "/config.inc.php...\n"; |
fd6b19
|
103 |
$written = $RCI->save_configfile($RCI->create_config()); |
461a30
|
104 |
} |
AM |
105 |
|
fee8c6
|
106 |
// Success! |
9bacb2
|
107 |
if ($written) { |
fee8c6
|
108 |
echo "Done.\n"; |
0da902
|
109 |
echo "Your configuration files are now up-to-date!\n"; |
471d55
|
110 |
|
TB |
111 |
if ($messages['missing']) { |
|
112 |
echo "But you still need to add the following missing options:\n"; |
|
113 |
foreach ($messages['missing'] as $msg) |
|
114 |
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n"; |
|
115 |
} |
9bacb2
|
116 |
|
TB |
117 |
if ($RCI->legacy_config) { |
|
118 |
foreach (array('main', 'db') as $file) { |
|
119 |
@unlink(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php'); |
|
120 |
} |
|
121 |
} |
fee8c6
|
122 |
} |
T |
123 |
else { |
461a30
|
124 |
echo "Failed to write config file(s)!\n"; |
fee8c6
|
125 |
echo "Grant write privileges to the current user or update the files manually according to the above messages.\n"; |
T |
126 |
} |
|
127 |
} |
|
128 |
else { |
7e7431
|
129 |
echo "Please update your config files manually according to the above messages.\n"; |
fee8c6
|
130 |
} |
T |
131 |
} |
|
132 |
|
|
133 |
// check dependencies based on the current configuration |
|
134 |
if (is_array($messages['dependencies'])) { |
|
135 |
echo "WARNING: Dependency check failed!\n"; |
|
136 |
echo "(Some of your configuration settings require other options to be configured or additional PHP modules to be installed)\n"; |
|
137 |
|
|
138 |
foreach ($messages['dependencies'] as $msg) { |
|
139 |
echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n"; |
|
140 |
} |
|
141 |
echo "Please fix your config files and run this script again!\n"; |
|
142 |
echo "See ya.\n"; |
|
143 |
} |
|
144 |
} |
2491c6
|
145 |
|
8f49e4
|
146 |
// check file type detection |
TB |
147 |
if ($RCI->check_mime_detection()) { |
|
148 |
echo "WARNING: File type detection doesn't work properly!\n"; |
e8dd47
|
149 |
echo "Please check the 'mime_magic' config option or the finfo functions of PHP and run this script again.\n"; |
8f49e4
|
150 |
} |
TB |
151 |
if ($RCI->check_mime_extensions()) { |
|
152 |
echo "WARNING: Mimetype to file extension mapping doesn't work properly!\n"; |
|
153 |
echo "Please check the 'mime_types' config option and run this script again.\n"; |
|
154 |
} |
|
155 |
|
2491c6
|
156 |
// check database schema |
T |
157 |
if ($RCI->config['db_dsnw']) { |
7e7431
|
158 |
echo "Executing database schema update.\n"; |
e76208
|
159 |
$success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'], |
AM |
160 |
array('errors' => true)); |
2491c6
|
161 |
} |
7e7431
|
162 |
|
0c137f
|
163 |
// update composer dependencies |
TB |
164 |
if (is_file(INSTALL_PATH . 'composer.json') && is_readable(INSTALL_PATH . 'composer.json-dist')) { |
|
165 |
$composer_data = json_decode(file_get_contents(INSTALL_PATH . 'composer.json'), true); |
|
166 |
$composer_template = json_decode(file_get_contents(INSTALL_PATH . 'composer.json-dist'), true); |
|
167 |
$comsposer_json = null; |
|
168 |
|
|
169 |
// update the require section with the new dependencies |
|
170 |
if (is_array($composer_data['require']) && is_array($composer_template['require'])) { |
|
171 |
$composer_data['require'] = array_merge($composer_data['require'], $composer_template['require']); |
26c400
|
172 |
|
TB |
173 |
// remove obsolete packages |
|
174 |
$old_packages = array( |
|
175 |
'pear/mail_mime', |
|
176 |
'pear/mail_mime-decode', |
|
177 |
'pear/net_smtp', |
|
178 |
'pear/net_sieve', |
|
179 |
'pear-pear.php.net/net_sieve', |
|
180 |
); |
|
181 |
foreach ($old_packages as $pkg) { |
|
182 |
if (array_key_exists($pkg, $composer_data['require'])) { |
0c137f
|
183 |
unset($composer_data['require'][$pkg]); |
TB |
184 |
} |
|
185 |
} |
|
186 |
} |
|
187 |
|
9a3fe2
|
188 |
// update the repositories section with the new dependencies |
TB |
189 |
if (is_array($composer_template['repositories'])) { |
|
190 |
if (!is_array($composer_data['repositories'])) { |
|
191 |
$composer_data['repositories'] = array(); |
|
192 |
} |
|
193 |
|
|
194 |
foreach ($composer_template['repositories'] as $repo) { |
a612c5
|
195 |
$rkey = $repo['type'] . preg_replace('/^https?:/', '', $repo['url']) . $repo['package']['name']; |
9a3fe2
|
196 |
$existing = false; |
a612c5
|
197 |
foreach ($composer_data['repositories'] as $k => $_repo) { |
TB |
198 |
if ($rkey == $_repo['type'] . preg_replace('/^https?:/', '', $_repo['url']) . $_repo['package']['name']) { |
26c400
|
199 |
// switch to https:// |
TB |
200 |
if (isset($_repo['url']) && strpos($_repo['url'], 'http://') === 0) |
|
201 |
$composer_data['repositories'][$k]['url'] = 'https:' . substr($_repo['url'], 5); |
9a3fe2
|
202 |
$existing = true; |
TB |
203 |
break; |
a612c5
|
204 |
} |
TB |
205 |
// remove old repos |
|
206 |
else if (strpos($_repo['url'], 'git://git.kolab.org') === 0) { |
26c400
|
207 |
unset($composer_data['repositories'][$k]); |
TB |
208 |
} |
|
209 |
else if ($_repo['type'] == 'package' && $_repo['package']['name'] == 'Net_SMTP') { |
|
210 |
unset($composer_data['repositories'][$k]); |
9a3fe2
|
211 |
} |
TB |
212 |
} |
|
213 |
if (!$existing) { |
|
214 |
$composer_data['repositories'][] = $repo; |
|
215 |
} |
|
216 |
} |
a612c5
|
217 |
|
TB |
218 |
$composer_data['repositories'] = array_values($composer_data['repositories']); |
9a3fe2
|
219 |
} |
TB |
220 |
|
0c137f
|
221 |
// use the JSON encoder from the Composer package |
TB |
222 |
if (is_file('composer.phar')) { |
|
223 |
include 'phar://composer.phar/src/Composer/Json/JsonFile.php'; |
|
224 |
$comsposer_json = \Composer\Json\JsonFile::encode($composer_data); |
|
225 |
} |
|
226 |
// PHP 5.4's json_encode() does the job, too |
|
227 |
else if (defined('JSON_PRETTY_PRINT')) { |
a612c5
|
228 |
$comsposer_json = json_encode($composer_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); |
0c137f
|
229 |
} |
TB |
230 |
else { |
|
231 |
$success = false; |
|
232 |
$comsposer_json = null; |
|
233 |
} |
|
234 |
|
|
235 |
// write updated composer.json back to disk |
8d9945
|
236 |
if ($comsposer_json && is_writeable(INSTALL_PATH . 'composer.json')) { |
0c137f
|
237 |
$success &= (bool)file_put_contents(INSTALL_PATH . 'composer.json', $comsposer_json); |
TB |
238 |
} |
|
239 |
else { |
|
240 |
echo "WARNING: unable to update composer.json!\n"; |
|
241 |
echo "Please replace the 'require' section in your composer.json with the following:\n"; |
|
242 |
|
|
243 |
$require_json = ''; |
|
244 |
foreach ($composer_data['require'] as $pkg => $ver) { |
|
245 |
$require_json .= sprintf(' "%s": "%s",'."\n", $pkg, $ver); |
|
246 |
} |
|
247 |
|
|
248 |
echo ' "require": {'."\n"; |
|
249 |
echo rtrim($require_json, ",\n"); |
|
250 |
echo "\n }\n\n"; |
|
251 |
} |
|
252 |
|
|
253 |
echo "NOTE: Update dependencies by running `php composer.phar update --no-dev`\n"; |
|
254 |
} |
|
255 |
|
faf10e
|
256 |
// index contacts for fulltext searching |
447fc6
|
257 |
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) { |
e76208
|
258 |
rcmail_utils::indexcontacts(); |
faf10e
|
259 |
} |
7e7431
|
260 |
|
2491c6
|
261 |
if ($success) { |
e019f2
|
262 |
echo "This instance of Roundcube is up-to-date.\n"; |
fee8c6
|
263 |
echo "Have fun!\n"; |
T |
264 |
} |
|
265 |
} |
|
266 |
else { |
e019f2
|
267 |
echo "This instance of Roundcube is not yet configured!\n"; |
fee8c6
|
268 |
echo "Open http://url-to-roundcube/installer/ in your browser and follow the instuctions.\n"; |
T |
269 |
} |
|
270 |
|
d48470
|
271 |
?> |