1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package CleverStyle CMS |
4
|
|
|
* @subpackage Installer |
5
|
|
|
* @author Nazar Mokrynskyi <[email protected]> |
6
|
|
|
* @copyright Copyright (c) 2011-2016, Nazar Mokrynskyi |
7
|
|
|
* @license MIT License, see license.txt |
8
|
|
|
*/ |
9
|
|
|
namespace cs; |
10
|
|
|
use |
11
|
|
|
h; |
12
|
|
|
|
13
|
|
|
function install_form () { |
14
|
|
|
$timezones = get_timezones_list(); |
15
|
|
|
return h::{'form[method=post]'}( |
16
|
|
|
h::nav( |
17
|
|
|
h::{'radio[name=mode]'}( |
18
|
|
|
[ |
19
|
|
|
'value' => ['1', '0'], |
20
|
|
|
'in' => [h::span('Regular user'), h::span('Expert')], |
21
|
|
|
'onclick' => |
22
|
|
|
"var items = document.getElementsByClassName('expert');" |
23
|
|
|
."for (var i = 0; i < items.length; i++) {" |
24
|
|
|
."items.item(i).style.display = this.value == '0' ? 'table-row' : '';" |
25
|
|
|
."}" |
26
|
|
|
] |
27
|
|
|
) |
28
|
|
|
). |
29
|
|
|
h::table( |
30
|
|
|
h::{'tr td'}( |
31
|
|
|
'Site name:', |
32
|
|
|
h::{'input[name=site_name]'}() |
33
|
|
|
). |
34
|
|
|
h::{'tr.expert td'}( |
35
|
|
|
'Database engine:', |
36
|
|
|
h::{'select[name=db_engine][size=3][selected=MySQLi]'}( |
37
|
|
|
file_get_json(DIR.'/db_engines.json') |
38
|
|
|
) |
39
|
|
|
). |
40
|
|
|
h::{'tr.expert td'}( |
41
|
|
|
'Database host:', |
42
|
|
|
h::{'input[name=db_host][value=localhost]'}( |
43
|
|
|
[ |
44
|
|
|
'placeholder' => 'Relative or absolute path to DB for SQLite' |
45
|
|
|
] |
46
|
|
|
) |
47
|
|
|
). |
48
|
|
|
h::{'tr td'}( |
49
|
|
|
'Database name:', |
50
|
|
|
h::{'input[name=db_name]'}() |
51
|
|
|
). |
52
|
|
|
h::{'tr td'}( |
53
|
|
|
'Database user:', |
54
|
|
|
h::{'input[name=db_user]'}() |
55
|
|
|
). |
56
|
|
|
h::{'tr td'}( |
57
|
|
|
'Database user password:', |
58
|
|
|
h::{'input[type=password][name=db_password]'}() |
59
|
|
|
). |
60
|
|
|
h::{'tr.expert td'}( |
61
|
|
|
'Database tables prefix:', |
62
|
|
|
h::{'input[name=db_prefix]'}( |
63
|
|
|
[ |
64
|
|
|
'value' => substr(md5(random_bytes(1000)), 0, 5).'_' |
65
|
|
|
] |
66
|
|
|
) |
67
|
|
|
). |
68
|
|
|
h::{'tr.expert td'}( |
69
|
|
|
'Database charset:', |
70
|
|
|
h::{'input[name=db_charset][value=utf8mb4]'}() |
71
|
|
|
). |
72
|
|
|
h::{'tr td'}( |
73
|
|
|
'Timezone:', |
74
|
|
|
h::{'select[name=timezone][size=7][selected=UTC]'}( |
75
|
|
|
[ |
76
|
|
|
'in' => array_keys($timezones), |
77
|
|
|
'value' => array_values($timezones) |
78
|
|
|
] |
79
|
|
|
) |
80
|
|
|
). |
81
|
|
|
h::{'tr td'}( |
82
|
|
|
'Language:', |
83
|
|
|
h::{'select[name=language][size=3][selected=English]'}( |
84
|
|
|
file_get_json(DIR.'/languages.json') |
85
|
|
|
) |
86
|
|
|
). |
87
|
|
|
h::{'tr td'}( |
88
|
|
|
'Email of administrator:', |
89
|
|
|
h::{'input[type=email][name=admin_email]'}() |
90
|
|
|
). |
91
|
|
|
h::{'tr td'}( |
92
|
|
|
'Administrator password:', |
93
|
|
|
h::{'input[type=password][name=admin_password]'}() |
94
|
|
|
) |
95
|
|
|
). |
96
|
|
|
h::{'button.readme'}( |
97
|
|
|
'Readme', |
98
|
|
|
[ |
99
|
|
|
'onclick' => "window.open('readme.html', 'readme', 'location=no')" |
100
|
|
|
] |
101
|
|
|
). |
102
|
|
|
h::{'button.license'}( |
103
|
|
|
'License', |
104
|
|
|
[ |
105
|
|
|
'onclick' => "window.open('license.txt', 'license', 'location=no')" |
106
|
|
|
] |
107
|
|
|
). |
108
|
|
|
h::{'button[type=submit]'}( |
109
|
|
|
'Install' |
110
|
|
|
) |
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param array[] $fs |
116
|
|
|
* @param array|null $argv |
117
|
|
|
* |
118
|
|
|
* @return string |
119
|
|
|
*/ |
120
|
|
|
function install_process ($fs, $argv = null) { |
121
|
|
|
/** |
122
|
|
|
* Connecting to the DataBase |
123
|
|
|
*/ |
124
|
|
|
define('DEBUG', false); |
125
|
|
|
/** |
126
|
|
|
* DataBase structure import |
127
|
|
|
*/ |
128
|
|
|
if (!file_exists(DIR."/install/DB/$_POST[db_engine].sql")) { |
129
|
|
|
return "Can't find system tables structure for selected database engine! Installation aborted."; |
130
|
|
|
} |
131
|
|
|
$Request = Request::instance(); |
132
|
|
|
/** |
133
|
|
|
* General system configuration |
134
|
|
|
*/ |
135
|
|
|
if (isset($_POST['site_url'])) { |
136
|
|
|
$url = $_POST['site_url']; |
137
|
|
|
} else { |
138
|
|
|
$Request->init_server($_SERVER); |
139
|
|
|
$url = "$Request->scheme://$Request->host$Request->path"; |
140
|
|
|
$url = implode('/', array_slice(explode('/', $url), 0, -2)); //Remove 2 last items |
141
|
|
|
} |
142
|
|
|
preg_match('#//([^/]+)#', $url, $domain); |
143
|
|
|
$domain = explode(':', $domain[1])[0]; |
144
|
|
|
$config = [ |
145
|
|
|
'name' => $_POST['site_name'], |
146
|
|
|
'url' => [$url], |
147
|
|
|
'admin_email' => $_POST['admin_email'], |
148
|
|
|
'closed_title' => 'Site closed', |
149
|
|
|
'closed_text' => '<p>Site closed for maintenance</p>', |
150
|
|
|
'site_mode' => 1, |
151
|
|
|
'title_delimiter' => ' | ', |
152
|
|
|
'title_reverse' => 0, |
153
|
|
|
'cache_compress_js_css' => 1, |
154
|
|
|
'vulcanization' => 1, |
155
|
|
|
'put_js_after_body' => 1, |
156
|
|
|
'theme' => 'CleverStyle', |
157
|
|
|
'language' => $_POST['language'], |
158
|
|
|
'active_languages' => [$_POST['language']], |
159
|
|
|
'multilingual' => 0, |
160
|
|
|
'db_balance' => 0, |
161
|
|
|
'db_mirror_mode' => \cs\DB::MIRROR_MODE_MASTER_MASTER, |
162
|
|
|
'cookie_prefix' => '', |
163
|
|
|
'cookie_domain' => [$domain], |
164
|
|
|
'inserts_limit' => 1000, |
165
|
|
|
'key_expire' => 120, |
166
|
|
|
'gravatar_support' => 0, |
167
|
|
|
'session_expire' => 2592000, |
168
|
|
|
'update_ratio' => 75, |
169
|
|
|
'sign_in_attempts_block_count' => 0, |
170
|
|
|
'sign_in_attempts_block_time' => 5, |
171
|
|
|
'timezone' => $_POST['timezone'], |
172
|
|
|
'password_min_length' => 4, |
173
|
|
|
'password_min_strength' => 3, |
174
|
|
|
'smtp' => 0, |
175
|
|
|
'smtp_host' => '', |
176
|
|
|
'smtp_port' => '', |
177
|
|
|
'smtp_secure' => '', |
178
|
|
|
'smtp_auth' => 0, |
179
|
|
|
'smtp_user' => '', |
180
|
|
|
'smtp_password' => '', |
181
|
|
|
'mail_from' => $_POST['admin_email'], |
182
|
|
|
'mail_from_name' => "Administrator of $_POST[site_name]", |
183
|
|
|
'allow_user_registration' => 1, |
184
|
|
|
'require_registration_confirmation' => 1, |
185
|
|
|
'auto_sign_in_after_registration' => 1, |
186
|
|
|
'registration_confirmation_time' => 1, |
187
|
|
|
'mail_signature' => '', |
188
|
|
|
'remember_user_ip' => 0, |
189
|
|
|
'simple_admin_mode' => !isset($_POST['mode']) || $_POST['mode'] ? 1 : 0, |
190
|
|
|
'default_module' => 'System' |
191
|
|
|
]; |
192
|
|
|
/** |
193
|
|
|
* Extracting of engine's files |
194
|
|
|
*/ |
195
|
|
|
$extracted = array_filter( |
196
|
|
|
array_map( |
197
|
|
|
function ($index, $file) { |
198
|
|
|
$dir = dirname(ROOT."/$file"); |
199
|
|
|
if ( |
200
|
|
|
!@mkdir($dir, 0770, true) && |
201
|
|
|
!is_dir($dir) |
202
|
|
|
) { |
203
|
|
|
return false; |
204
|
|
|
} |
205
|
|
|
/** |
206
|
|
|
* TODO: copy() + file_exists() is a hack for HHVM, when bug fixed upstream (copying of empty files) this should be simplified |
207
|
|
|
*/ |
208
|
|
|
copy(DIR."/fs/$index", ROOT."/$file"); |
209
|
|
|
return file_exists(ROOT."/$file"); |
210
|
|
|
}, |
211
|
|
|
$fs, |
212
|
|
|
array_keys($fs) |
213
|
|
|
) |
214
|
|
|
); |
215
|
|
|
if ( |
216
|
|
|
count($extracted) !== count($fs) || |
217
|
|
|
( |
218
|
|
|
!@mkdir(ROOT.'/storage', 0770) && !is_dir(ROOT.'/storage') |
219
|
|
|
) || |
220
|
|
|
!file_put_contents(ROOT.'/storage/.htaccess', "Deny from all\nRewriteEngine Off\n<Files *>\n\tSetHandler default-handler\n</Files>") |
221
|
|
|
) { |
222
|
|
|
return "Can't extract system files from the archive! Installation aborted."; |
223
|
|
|
} |
224
|
|
|
/** |
225
|
|
|
* Basic system configuration |
226
|
|
|
*/ |
227
|
|
|
$public_key = hash('sha512', random_bytes(1000)); |
228
|
|
|
$main_config = is_dir(ROOT.'/config') && file_put_contents( |
229
|
|
|
ROOT.'/config/main.json', |
230
|
|
|
str_replace( |
231
|
|
|
[ |
232
|
|
|
'@domain', |
233
|
|
|
'@timezone', |
234
|
|
|
'@db_host', |
235
|
|
|
'@db_type', |
236
|
|
|
'@db_name', |
237
|
|
|
'@db_user', |
238
|
|
|
'@db_password', |
239
|
|
|
'@db_prefix', |
240
|
|
|
'@db_charset', |
241
|
|
|
'@language', |
242
|
|
|
'@public_key' |
243
|
|
|
], |
244
|
|
|
[ |
245
|
|
|
$config['cookie_domain'][0], |
246
|
|
|
$_POST['timezone'], |
247
|
|
|
$_POST['db_host'], |
248
|
|
|
$_POST['db_engine'], |
249
|
|
|
$_POST['db_name'], |
250
|
|
|
$_POST['db_user'], |
251
|
|
|
str_replace('"', '\\"', $_POST['db_password']), |
252
|
|
|
$_POST['db_prefix'], |
253
|
|
|
$_POST['db_charset'], |
254
|
|
|
$_POST['language'], |
255
|
|
|
$public_key |
256
|
|
|
], |
257
|
|
|
/** @lang JSON */ |
258
|
|
|
<<<CONFIG |
259
|
|
|
{ |
260
|
|
|
//Domain of main mirror |
261
|
|
|
"domain" : "@domain", |
262
|
|
|
//Base timezone |
263
|
|
|
"timezone" : "@timezone", |
264
|
|
|
//Settings of main DB |
265
|
|
|
"db_host" : "@db_host", |
266
|
|
|
"db_type" : "@db_type", |
267
|
|
|
"db_name" : "@db_name", |
268
|
|
|
"db_user" : "@db_user", |
269
|
|
|
"db_password" : "@db_password", |
270
|
|
|
"db_prefix" : "@db_prefix", |
271
|
|
|
"db_charset" : "@db_charset", |
272
|
|
|
//Settings of main Storage |
273
|
|
|
"storage_type" : "Local", |
274
|
|
|
"storage_url" : "", |
275
|
|
|
"storage_host" : "localhost", |
276
|
|
|
"storage_user" : "", |
277
|
|
|
"storage_password" : "", |
278
|
|
|
//Base language |
279
|
|
|
"language" : "@language", |
280
|
|
|
//Cache engine |
281
|
|
|
"cache_engine" : "FileSystem", |
282
|
|
|
//Settings of Memcached cache engine |
283
|
|
|
"memcache_host" : "127.0.0.1", |
284
|
|
|
"memcache_port" : "11211", |
285
|
|
|
//Any length |
286
|
|
|
"public_key" : "@public_key" |
287
|
|
|
} |
288
|
|
|
CONFIG |
289
|
|
|
) |
290
|
|
|
); |
291
|
|
|
extension_loaded('apc') && apc_clear_cache('user'); |
292
|
|
|
if (!$main_config) { |
293
|
|
|
return "Can't write base system configuration! Installation aborted."; |
294
|
|
|
} |
295
|
|
|
chmod(ROOT.'/config/main.json', 0600); |
296
|
|
|
/** |
297
|
|
|
* @var \cs\DB\_Abstract $cdb |
298
|
|
|
*/ |
299
|
|
|
$cdb = "cs\\DB\\$_POST[db_engine]"; |
300
|
|
|
$cdb = new $cdb( |
301
|
|
|
$_POST['db_name'], |
302
|
|
|
$_POST['db_user'], |
303
|
|
|
$_POST['db_password'], |
304
|
|
|
$_POST['db_host'], |
305
|
|
|
$_POST['db_charset'], |
306
|
|
|
$_POST['db_prefix'] |
307
|
|
|
); |
308
|
|
|
if (!is_object($cdb) || !$cdb->connected()) { |
309
|
|
|
return 'Database connection failed! Installation aborted.'; |
310
|
|
|
} |
311
|
|
|
if (!$cdb->q( |
312
|
|
|
array_filter( |
313
|
|
|
explode(';', file_get_contents(DIR."/install/DB/$_POST[db_engine].sql")), |
314
|
|
|
'_trim' |
315
|
|
|
) |
316
|
|
|
) |
317
|
|
|
) { |
318
|
|
|
return "Can't import system tables structure for selected database engine! Installation aborted."; |
319
|
|
|
} |
320
|
|
|
/** |
321
|
|
|
* General configuration import |
322
|
|
|
*/ |
323
|
|
|
$modules = [ |
324
|
|
|
'System' => [ |
325
|
|
|
'active' => Config\Module_Properties::ENABLED, |
326
|
|
|
'db' => [ |
327
|
|
|
'keys' => '0', |
328
|
|
|
'users' => '0', |
329
|
|
|
'texts' => '0' |
330
|
|
|
] |
331
|
|
|
] |
332
|
|
|
]; |
333
|
|
|
if (file_exists(DIR.'/modules.json')) { |
334
|
|
|
foreach (file_get_json(DIR.'/modules.json') as $module) { |
335
|
|
|
$modules[$module] = [ |
336
|
|
|
'active' => Config\Module_Properties::UNINSTALLED, |
337
|
|
|
'db' => [], |
338
|
|
|
'storage' => [] |
339
|
|
|
]; |
340
|
|
|
} |
341
|
|
|
unset($module); |
342
|
|
|
} |
343
|
|
|
if (!$cdb->q( |
344
|
|
|
"INSERT INTO `[prefix]config` ( |
345
|
|
|
`domain`, `core`, `db`, `storage`, `components` |
346
|
|
|
) VALUES ( |
347
|
|
|
'%s', '%s', '[]', '[]', '%s' |
348
|
|
|
)", |
349
|
|
|
$config['cookie_domain'][0], |
350
|
|
|
_json_encode($config), |
351
|
|
|
'{"modules":'._json_encode($modules).',"plugins":[],"blocks":[]}' |
352
|
|
|
) |
353
|
|
|
) { |
354
|
|
|
return "Can't import system configuration into database! Installation aborted."; |
355
|
|
|
} |
356
|
|
|
unset($modules); |
357
|
|
|
/** |
358
|
|
|
* Administrator registration |
359
|
|
|
*/ |
360
|
|
|
$admin_login = strstr($_POST['admin_email'], '@', true); |
361
|
|
|
if (!$cdb->q( |
362
|
|
|
"INSERT INTO `[prefix]users` ( |
363
|
|
|
`login`, `login_hash`, `password_hash`, `email`, `email_hash`, `reg_date`, `reg_ip`, `status` |
364
|
|
|
) VALUES ( |
365
|
|
|
'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' |
366
|
|
|
)", |
367
|
|
|
$admin_login, |
368
|
|
|
hash('sha224', $admin_login), |
369
|
|
|
password_hash(hash('sha512', hash('sha512', $_POST['admin_password']).$public_key), PASSWORD_DEFAULT), |
370
|
|
|
$_POST['admin_email'], |
371
|
|
|
hash('sha224', $_POST['admin_email']), |
372
|
|
|
time(), |
373
|
|
|
ip2hex($Request->remote_addr), |
374
|
|
|
1 |
375
|
|
|
) |
376
|
|
|
) { |
377
|
|
|
return "Can't register administrator user! Installation aborted."; |
378
|
|
|
} |
379
|
|
|
/** |
380
|
|
|
* Disconnecting from the DataBase |
381
|
|
|
*/ |
382
|
|
|
$cdb->__destruct(); |
383
|
|
|
$warning = false; |
384
|
|
|
// Removing of installer file |
385
|
|
|
$cli = PHP_SAPI == 'cli'; |
386
|
|
|
$installer = $cli ? ROOT."/$argv[0]" : ROOT.'/'.pathinfo(DIR, PATHINFO_BASENAME); |
387
|
|
|
if (!is_writable($installer) || !unlink($installer)) { |
388
|
|
|
$warning = "Please, remove installer file $installer for security!\n"; |
389
|
|
|
} |
390
|
|
|
if ($cli) { |
391
|
|
|
return "Congratulations! CleverStyle CMS has been installed successfully!\n$warning\nLogin: $admin_login\nPassword: $_POST[admin_password]"; |
392
|
|
|
} else { |
393
|
|
|
return |
394
|
|
|
h::h3( |
395
|
|
|
'Congratulations! CleverStyle CMS has been installed successfully!' |
396
|
|
|
). |
397
|
|
|
h::{'table tr| td'}( |
398
|
|
|
[ |
399
|
|
|
'Your sign in information:', |
400
|
|
|
[ |
401
|
|
|
'colspan' => 2 |
402
|
|
|
] |
403
|
|
|
], |
404
|
|
|
[ |
405
|
|
|
'Login:', |
406
|
|
|
$admin_login |
407
|
|
|
], |
408
|
|
|
[ |
409
|
|
|
'Password:', |
410
|
|
|
$_POST['admin_password'] |
411
|
|
|
] |
412
|
|
|
). |
413
|
|
|
h::p( |
414
|
|
|
$warning, |
415
|
|
|
[ |
416
|
|
|
'style' => 'color: red;' |
417
|
|
|
] |
418
|
|
|
). |
419
|
|
|
h::button( |
420
|
|
|
'Go to website', |
421
|
|
|
[ |
422
|
|
|
'onclick' => "location.href = '/';" |
423
|
|
|
] |
424
|
|
|
); |
425
|
|
|
} |
426
|
|
|
} |
427
|
|
|
|