Commit | Line | Data |
---|---|---|
158bd3ca TD |
1 | <?php |
2 | namespace wcf\system; | |
3 | use wcf\data\language\LanguageEditor; | |
4 | use wcf\data\language\SetupLanguage; | |
89142da9 | 5 | use wcf\data\package\installation\queue\PackageInstallationQueueEditor; |
158bd3ca TD |
6 | use wcf\data\user\User; |
7 | use wcf\data\user\UserAction; | |
b401cd0d | 8 | use wcf\system\cache\builder\LanguageCacheBuilder; |
158bd3ca TD |
9 | use wcf\system\database\util\SQLParser; |
10 | use wcf\system\exception\SystemException; | |
8a81a7bd | 11 | use wcf\system\exception\UserInputException; |
158bd3ca TD |
12 | use wcf\system\io\File; |
13 | use wcf\system\io\Tar; | |
14 | use wcf\system\language\LanguageFactory; | |
15 | use wcf\system\package\PackageArchive; | |
16 | use wcf\system\session\ACPSessionFactory; | |
17 | use wcf\system\session\SessionHandler; | |
18 | use wcf\system\setup\Installer; | |
19 | use wcf\system\template\SetupTemplateEngine; | |
931f6597 | 20 | use wcf\system\Regex; |
2bc9f31d | 21 | use wcf\system\WCF; |
364a2e49 | 22 | use wcf\util\DirectoryUtil; |
158bd3ca TD |
23 | use wcf\util\FileUtil; |
24 | use wcf\util\StringUtil; | |
25 | use wcf\util\UserUtil; | |
26 | use wcf\util\XML; | |
27 | ||
28 | // define | |
29 | define('PACKAGE_ID', '0'); | |
30 | define('HTTP_ENABLE_NO_CACHE_HEADERS', 0); | |
31 | define('HTTP_ENABLE_GZIP', 0); | |
32 | define('HTTP_GZIP_LEVEL', 0); | |
33 | define('CACHE_SOURCE_TYPE', 'disk'); | |
158bd3ca | 34 | define('MODULE_MASTER_PASSWORD', 1); |
0c07c50c | 35 | define('ENABLE_DEBUG_MODE', 1); |
8a12b687 | 36 | define('ENABLE_BENCHMARK', 0); |
158bd3ca TD |
37 | |
38 | /** | |
a17de04e MS |
39 | * Executes the installation of the basic WCF systems. |
40 | * | |
9f959ced | 41 | * @author Marcel Werk |
b4f1ea02 | 42 | * @copyright 2001-2013 WoltLab GmbH |
158bd3ca TD |
43 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
44 | * @package com.woltlab.wcf | |
45 | * @subpackage system | |
9f959ced | 46 | * @category Community Framework |
158bd3ca TD |
47 | */ |
48 | class WCFSetup extends WCF { | |
9f959ced MS |
49 | /** |
50 | * list of available languages | |
51 | * @var array | |
52 | */ | |
158bd3ca | 53 | protected static $availableLanguages = array(); |
9f959ced MS |
54 | |
55 | /** | |
56 | * language code of selected installation language | |
57 | * @var string | |
58 | */ | |
158bd3ca | 59 | protected static $selectedLanguageCode = 'en'; |
9f959ced MS |
60 | |
61 | /** | |
62 | * selected languages to be installed | |
63 | * @var array | |
64 | */ | |
158bd3ca | 65 | protected static $selectedLanguages = array(); |
9f959ced MS |
66 | |
67 | /** | |
68 | * directory of the framework | |
69 | * @var string | |
70 | */ | |
158bd3ca | 71 | protected static $wcfDir = ''; |
9f959ced MS |
72 | |
73 | /** | |
74 | * list of installed files | |
75 | * @var array | |
76 | */ | |
158bd3ca | 77 | protected static $installedFiles = array(); |
9f959ced MS |
78 | |
79 | /** | |
80 | * name of installed primary application | |
81 | * @var string | |
82 | */ | |
158bd3ca | 83 | protected static $setupPackageName = 'WoltLab Community Framework'; |
9f959ced MS |
84 | |
85 | /** | |
86 | * indicates if developer mode is used to install | |
87 | * @var boolean | |
88 | */ | |
158bd3ca | 89 | protected static $developerMode = 0; |
9f959ced MS |
90 | |
91 | /** | |
92 | * supported databases | |
93 | * @var array<array> | |
94 | */ | |
158bd3ca | 95 | protected static $dbClasses = array( |
c17ae73c AE |
96 | 'MySQLDatabase' => array('class' => 'wcf\system\database\MySQLDatabase', 'minversion' => '5.1.17')//, // MySQL 5.1.17+ |
97 | //'PostgreSQLDatabase' => array('class' => 'wcf\system\database\PostgreSQLDatabase', 'minversion' => '8.2.0') // PostgreSQL 8.2.0+ | |
158bd3ca TD |
98 | ); |
99 | ||
100 | /** | |
101 | * Calls all init functions of the WCFSetup class and starts the setup process. | |
102 | */ | |
103 | public function __construct() { | |
104 | @set_time_limit(0); | |
105 | $this->initMagicQuotes(); | |
106 | $this->getDeveloperMode(); | |
107 | $this->getLanguageSelection(); | |
108 | $this->getWCFDir(); | |
109 | $this->initLanguage(); | |
110 | $this->initTPL(); | |
111 | self::getLanguage()->loadLanguage(); | |
112 | $this->getPackageName(); | |
113 | ||
114 | // start setup | |
115 | $this->setup(); | |
116 | } | |
117 | ||
118 | /** | |
119 | * Gets the status of the developer mode. | |
120 | */ | |
121 | protected static function getDeveloperMode() { | |
122 | if (isset($_GET['dev'])) self::$developerMode = intval($_GET['dev']); | |
123 | else if (isset($_POST['dev'])) self::$developerMode = intval($_POST['dev']); | |
124 | } | |
125 | ||
126 | /** | |
127 | * Gets the selected language. | |
128 | */ | |
129 | protected static function getLanguageSelection() { | |
1157f8be | 130 | self::$availableLanguages = self::getAvailableLanguages(); |
158bd3ca | 131 | |
1157f8be | 132 | if (isset($_REQUEST['languageCode']) && isset(self::$availableLanguages[$_REQUEST['languageCode']])) { |
158bd3ca TD |
133 | self::$selectedLanguageCode = $_REQUEST['languageCode']; |
134 | } | |
135 | else { | |
1157f8be | 136 | self::$selectedLanguageCode = LanguageFactory::getPreferredLanguage(array_keys(self::$availableLanguages), self::$selectedLanguageCode); |
158bd3ca TD |
137 | } |
138 | ||
139 | if (isset($_POST['selectedLanguages']) && is_array($_POST['selectedLanguages'])) { | |
140 | self::$selectedLanguages = $_POST['selectedLanguages']; | |
141 | } | |
142 | } | |
143 | ||
144 | /** | |
145 | * Gets the available database classes. | |
9f959ced | 146 | * |
158bd3ca TD |
147 | * @return array |
148 | */ | |
149 | protected static function getAvailableDBClasses() { | |
150 | $availableDBClasses = array(); | |
151 | foreach (self::$dbClasses as $class => $data) { | |
152 | if (call_user_func(array($data['class'], 'isSupported'))) { | |
153 | $availableDBClasses[$class] = $data; | |
154 | } | |
155 | } | |
156 | ||
157 | return $availableDBClasses; | |
158 | } | |
9f959ced | 159 | |
158bd3ca TD |
160 | /** |
161 | * Gets the selected wcf dir from request. | |
162 | */ | |
163 | protected static function getWCFDir() { | |
164 | if (isset($_REQUEST['wcfDir']) && $_REQUEST['wcfDir'] != '') { | |
165 | self::$wcfDir = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator($_REQUEST['wcfDir'])); | |
166 | if (@file_exists(self::$wcfDir)) { | |
167 | define('RELATIVE_WCF_DIR', FileUtil::getRelativePath(INSTALL_SCRIPT_DIR, self::$wcfDir)); | |
168 | } | |
169 | } | |
170 | ||
171 | define('WCF_DIR', self::$wcfDir); | |
172 | } | |
9f959ced | 173 | |
158bd3ca TD |
174 | /** |
175 | * Initialises the language engine. | |
176 | */ | |
177 | protected function initLanguage() { | |
178 | // set mb settings | |
179 | mb_internal_encoding('UTF-8'); | |
180 | if (function_exists('mb_regex_encoding')) mb_regex_encoding('UTF-8'); | |
181 | mb_language('uni'); | |
182 | ||
183 | // init setup language | |
184 | self::$languageObj = new SetupLanguage(null, array( | |
185 | 'languageCode' => self::$selectedLanguageCode | |
186 | )); | |
187 | } | |
188 | ||
189 | /** | |
190 | * Initialises the template engine. | |
191 | */ | |
192 | protected function initTPL() { | |
193 | self::$tplObj = SetupTemplateEngine::getInstance(); | |
1157f8be | 194 | self::getTPL()->setLanguageID((self::$selectedLanguageCode == 'en' ? 0 : 1)); |
158bd3ca | 195 | self::getTPL()->setCompileDir(TMP_DIR); |
669e16fe | 196 | self::getTPL()->addApplication('wcf', PACKAGE_ID, TMP_DIR); |
158bd3ca TD |
197 | self::getTPL()->registerPrefilter(array('lang')); |
198 | self::getTPL()->assign(array( | |
199 | '__wcf' => $this, | |
200 | 'tmpFilePrefix' => TMP_FILE_PREFIX, | |
201 | 'languageCode' => self::$selectedLanguageCode, | |
202 | 'selectedLanguages' => self::$selectedLanguages, | |
203 | 'wcfDir' => self::$wcfDir, | |
204 | 'developerMode' => self::$developerMode | |
205 | )); | |
206 | } | |
207 | ||
208 | /** | |
209 | * Returns all languages from WCFSetup.tar.gz. | |
9f959ced | 210 | * |
158bd3ca TD |
211 | * @return array |
212 | */ | |
1157f8be | 213 | protected static function getAvailableLanguages() { |
158bd3ca TD |
214 | $languages = $match = array(); |
215 | $tar = new Tar(SETUP_FILE); | |
216 | foreach ($tar->getContentList() as $file) { | |
1157f8be MW |
217 | if (strpos($file['filename'], 'setup/lang/') === 0 && substr($file['filename'], -4) == '.xml') { |
218 | $xml = new XML(); | |
219 | $xml->load(TMP_DIR.$file['filename']); | |
220 | $languageCode = LanguageEditor::readLanguageCodeFromXML($xml); | |
221 | $languageName = LanguageEditor::readLanguageNameFromXML($xml); | |
222 | ||
223 | $languages[$languageCode] = $languageName; | |
158bd3ca TD |
224 | } |
225 | } | |
226 | $tar->close(); | |
9f959ced | 227 | |
1157f8be MW |
228 | // sort languages by language name |
229 | asort($languages); | |
9f959ced | 230 | |
158bd3ca TD |
231 | return $languages; |
232 | } | |
233 | ||
234 | /** | |
235 | * Calculates the current state of the progress bar. | |
9f959ced | 236 | * |
158bd3ca TD |
237 | * @param integer $currentStep |
238 | */ | |
239 | protected function calcProgress($currentStep) { | |
158bd3ca | 240 | // calculate progress |
f5ad2373 | 241 | $progress = round((100 / 12) * ++$currentStep, 0); |
158bd3ca TD |
242 | self::getTPL()->assign(array('progress' => $progress)); |
243 | } | |
244 | ||
245 | /** | |
246 | * Executes the setup steps. | |
247 | */ | |
248 | protected function setup() { | |
249 | // get current step | |
250 | if (isset($_REQUEST['step'])) $step = $_REQUEST['step']; | |
251 | else $step = 'selectSetupLanguage'; | |
9f959ced | 252 | |
158bd3ca TD |
253 | // execute current step |
254 | switch ($step) { | |
255 | case 'selectSetupLanguage': | |
256 | if (!self::$developerMode) { | |
257 | $this->calcProgress(0); | |
258 | $this->selectSetupLanguage(); | |
259 | break; | |
260 | } | |
9f959ced | 261 | |
158bd3ca TD |
262 | case 'showLicense': |
263 | if (!self::$developerMode) { | |
264 | $this->calcProgress(1); | |
265 | $this->showLicense(); | |
266 | break; | |
267 | } | |
9f959ced | 268 | |
158bd3ca TD |
269 | case 'showSystemRequirements': |
270 | if (!self::$developerMode) { | |
271 | $this->calcProgress(2); | |
272 | $this->showSystemRequirements(); | |
273 | break; | |
274 | } | |
9f959ced | 275 | |
158bd3ca TD |
276 | case 'searchWcfDir': |
277 | $this->calcProgress(3); | |
278 | $this->searchWcfDir(); | |
9f959ced MS |
279 | break; |
280 | ||
158bd3ca TD |
281 | case 'unzipFiles': |
282 | $this->calcProgress(4); | |
283 | $this->unzipFiles(); | |
9f959ced MS |
284 | break; |
285 | ||
158bd3ca TD |
286 | case 'selectLanguages': |
287 | $this->calcProgress(5); | |
288 | $this->selectLanguages(); | |
9f959ced MS |
289 | break; |
290 | ||
158bd3ca TD |
291 | case 'configureDB': |
292 | $this->calcProgress(6); | |
293 | $this->configureDB(); | |
9f959ced MS |
294 | break; |
295 | ||
158bd3ca TD |
296 | case 'createDB': |
297 | $this->calcProgress(7); | |
298 | $this->createDB(); | |
9f959ced MS |
299 | break; |
300 | ||
158bd3ca TD |
301 | case 'logFiles': |
302 | $this->calcProgress(8); | |
303 | $this->logFiles(); | |
9f959ced MS |
304 | break; |
305 | ||
158bd3ca TD |
306 | case 'installLanguage': |
307 | $this->calcProgress(9); | |
308 | $this->installLanguage(); | |
9f959ced MS |
309 | break; |
310 | ||
158bd3ca TD |
311 | case 'createUser': |
312 | $this->calcProgress(10); | |
313 | $this->createUser(); | |
9f959ced MS |
314 | break; |
315 | ||
158bd3ca TD |
316 | case 'installPackages': |
317 | $this->calcProgress(11); | |
318 | $this->installPackages(); | |
9f959ced | 319 | break; |
158bd3ca TD |
320 | } |
321 | } | |
322 | ||
323 | /** | |
324 | * Shows the first setup page. | |
325 | */ | |
326 | protected function selectSetupLanguage() { | |
158bd3ca | 327 | WCF::getTPL()->assign(array( |
1157f8be | 328 | 'availableLanguages' => self::$availableLanguages, |
158bd3ca TD |
329 | 'nextStep' => 'showLicense' |
330 | )); | |
331 | WCF::getTPL()->display('stepSelectSetupLanguage'); | |
332 | } | |
333 | ||
334 | /** | |
335 | * Shows the license agreement. | |
336 | */ | |
337 | protected function showLicense() { | |
338 | if (isset($_POST['send'])) { | |
339 | if (isset($_POST['accepted'])) { | |
340 | $this->gotoNextStep('showSystemRequirements'); | |
341 | exit; | |
342 | } | |
343 | else { | |
344 | WCF::getTPL()->assign(array('missingAcception' => true)); | |
345 | } | |
346 | ||
347 | } | |
348 | ||
349 | if (file_exists(TMP_DIR.'setup/license/license_'.self::$selectedLanguageCode.'.txt')) { | |
350 | $license = file_get_contents(TMP_DIR.'setup/license/license_'.self::$selectedLanguageCode.'.txt'); | |
351 | } | |
352 | else { | |
353 | $license = file_get_contents(TMP_DIR.'setup/license/license_en.txt'); | |
354 | } | |
355 | ||
356 | WCF::getTPL()->assign(array( | |
357 | 'license' => $license, | |
358 | 'nextStep' => 'showLicense' | |
359 | )); | |
360 | WCF::getTPL()->display('stepShowLicense'); | |
361 | } | |
362 | ||
363 | /** | |
364 | * Shows the system requirements. | |
365 | */ | |
366 | protected function showSystemRequirements() { | |
367 | $system = array(); | |
368 | ||
369 | // php version | |
370 | $system['phpVersion']['value'] = phpversion(); | |
371 | $comparePhpVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $system['phpVersion']['value']); | |
cec6c73a | 372 | $system['phpVersion']['result'] = (version_compare($comparePhpVersion, '5.3.2') >= 0); |
158bd3ca TD |
373 | |
374 | // sql | |
375 | $system['sql']['value'] = array_keys(self::getAvailableDBClasses()); | |
15fa2802 | 376 | $system['sql']['result'] = !empty($system['sql']['value']); |
158bd3ca TD |
377 | |
378 | // upload_max_filesize | |
379 | $system['uploadMaxFilesize']['value'] = ini_get('upload_max_filesize'); | |
380 | $system['uploadMaxFilesize']['result'] = (intval($system['uploadMaxFilesize']['value']) > 0); | |
381 | ||
382 | // gdlib version | |
383 | $system['gdLib']['value'] = '0.0.0'; | |
384 | if (function_exists('gd_info')) { | |
385 | $temp = gd_info(); | |
386 | $match = array(); | |
387 | if (preg_match('!([0-9]+\.[0-9]+(?:\.[0-9]+)?)!', $temp['GD Version'], $match)) { | |
388 | if (preg_match('/^[0-9]+\.[0-9]+$/', $match[1])) $match[1] .= '.0'; | |
389 | $system['gdLib']['value'] = $match[1]; | |
390 | } | |
391 | } | |
392 | $system['gdLib']['result'] = (version_compare($system['gdLib']['value'], '2.0.0') >= 0); | |
393 | ||
394 | // mb string | |
395 | $system['mbString']['result'] = extension_loaded('mbstring'); | |
396 | ||
b4f1ea02 AE |
397 | // memory limit |
398 | $system['memoryLimit']['value'] = ini_get('memory_limit'); | |
399 | $system['memoryLimit']['result'] = $this->compareMemoryLimit(); | |
400 | ||
158bd3ca TD |
401 | WCF::getTPL()->assign(array( |
402 | 'system' => $system, | |
403 | 'nextStep' => 'searchWcfDir' | |
404 | )); | |
405 | WCF::getTPL()->display('stepShowSystemRequirements'); | |
406 | } | |
407 | ||
408 | /** | |
b4f1ea02 AE |
409 | * Returns true, if memory_limit is set to at least 64 MB |
410 | * | |
411 | * @return boolean | |
412 | */ | |
413 | protected function compareMemoryLimit() { | |
414 | $memoryLimit = ini_get('memory_limit'); | |
415 | ||
416 | // no limit | |
417 | if ($memoryLimit == -1) { | |
418 | return true; | |
419 | } | |
420 | ||
421 | // completely numeric, PHP assumes byte | |
422 | if (is_numeric($memoryLimit)) { | |
423 | $memoryLimit = $memoryLimit / 1024; | |
424 | return ($memoryLimit >= 64); | |
425 | } | |
426 | ||
427 | // PHP supports 'K', 'M' and 'G' shorthand notation | |
53e6372f | 428 | if (preg_match('~^(\d+)([KMG])$~', $memoryLimit, $matches)) { |
b4f1ea02 AE |
429 | switch ($matches[2]) { |
430 | case 'K': | |
431 | $memoryLimit = $matches[1] * 1024; | |
432 | return ($memoryLimit >= 64); | |
433 | break; | |
434 | ||
435 | case 'M': | |
436 | return ($matches[1] >= 64); | |
437 | break; | |
438 | ||
439 | case 'G': | |
440 | return ($matches[1] >= 1); | |
441 | break; | |
442 | } | |
443 | } | |
444 | ||
445 | return false; | |
446 | } | |
447 | ||
448 | /** | |
158bd3ca TD |
449 | * Searches the wcf dir. |
450 | */ | |
451 | protected function searchWcfDir() { | |
452 | $foundDirectory = ''; | |
453 | if (self::$wcfDir) { | |
454 | $wcfDir = self::$wcfDir; | |
455 | } | |
456 | else { | |
457 | if ($foundDirectory = FileUtil::scanFolder(INSTALL_SCRIPT_DIR, "WCF.class.php", true)) { | |
458 | $foundDirectory = $wcfDir = FileUtil::unifyDirSeperator(dirname(dirname(dirname($foundDirectory))).'/'); | |
459 | ||
460 | if (dirname(dirname($wcfDir)).'/' == TMP_DIR) { | |
461 | $foundDirectory = false; | |
462 | $wcfDir = FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR).'wcf/'; | |
463 | } | |
464 | } | |
465 | else { | |
466 | $wcfDir = FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR).'wcf/'; | |
467 | } | |
468 | } | |
469 | ||
470 | // domain | |
471 | $domainName = ''; | |
472 | if (!empty($_SERVER['SERVER_NAME'])) $domainName = 'http://' . $_SERVER['SERVER_NAME']; | |
473 | // port | |
474 | if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80) $domainName .= ':' . $_SERVER['SERVER_PORT']; | |
475 | // script url | |
476 | $installScriptUrl = ''; | |
477 | if (!empty($_SERVER['REQUEST_URI'])) $installScriptUrl = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash(FileUtil::unifyDirSeperator(dirname($_SERVER['REQUEST_URI'])))); | |
478 | ||
479 | WCF::getTPL()->assign(array( | |
480 | 'nextStep' => 'unzipFiles', | |
481 | 'foundDirectory' => $foundDirectory, | |
482 | 'wcfDir' => $wcfDir, | |
483 | 'domainName' => $domainName, | |
484 | 'installScriptUrl' => $installScriptUrl, | |
485 | 'installScriptDir' => FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR) | |
486 | )); | |
487 | ||
488 | WCF::getTPL()->display('stepSearchWcfDir'); | |
489 | } | |
490 | ||
491 | /** | |
492 | * Unzips the files of the wcfsetup tar archive. | |
493 | */ | |
494 | protected function unzipFiles() { | |
a17de04e MS |
495 | // WCF seems to be installed, skip installation of files, database |
496 | // and admin account and go directly to the installation of packages | |
158bd3ca TD |
497 | if (@is_file(self::$wcfDir.'lib/system/WCF.class.php')) { |
498 | $this->gotoNextStep('installPackages'); | |
499 | exit; | |
500 | } | |
501 | // WCF not yet installed, install files first | |
502 | else { | |
503 | try { | |
504 | $this->installFiles(); | |
505 | } | |
6286572b | 506 | catch (\Exception $e) { |
158bd3ca TD |
507 | WCF::getTPL()->assign(array('exception' => $e)); |
508 | $this->searchWcfDir(); | |
509 | return; | |
510 | } | |
511 | ||
512 | $this->gotoNextStep('selectLanguages'); | |
513 | } | |
514 | } | |
515 | ||
516 | /** | |
517 | * Shows the page for choosing the installed languages. | |
518 | */ | |
519 | protected function selectLanguages() { | |
520 | $errorField = $errorType = ''; | |
158bd3ca | 521 | |
158bd3ca TD |
522 | // skip step in developer mode |
523 | // select all available languages automatically | |
524 | if (self::$developerMode) { | |
525 | self::$selectedLanguages = array(); | |
f2f5a09c | 526 | foreach (self::$availableLanguages as $languageCode => $language) { |
158bd3ca TD |
527 | self::$selectedLanguages[] = $languageCode; |
528 | } | |
529 | ||
530 | self::getTPL()->assign(array('selectedLanguages' => self::$selectedLanguages)); | |
531 | $this->gotoNextStep('configureDB'); | |
532 | exit; | |
533 | } | |
534 | ||
158bd3ca TD |
535 | // start error handling |
536 | if (isset($_POST['send'])) { | |
537 | try { | |
538 | // no languages selected | |
15fa2802 | 539 | if (empty(self::$selectedLanguages)) { |
158bd3ca TD |
540 | throw new UserInputException('selectedLanguages'); |
541 | } | |
542 | ||
543 | // illegal selection | |
544 | foreach (self::$selectedLanguages as $language) { | |
1157f8be | 545 | if (!isset(self::$availableLanguages[$language])) { |
158bd3ca TD |
546 | throw new UserInputException('selectedLanguages'); |
547 | } | |
548 | } | |
549 | ||
550 | // no errors | |
551 | // go to next step | |
552 | $this->gotoNextStep('configureDB'); | |
553 | exit; | |
554 | } | |
555 | catch (UserInputException $e) { | |
556 | $errorField = $e->getField(); | |
557 | $errorType = $e->getType(); | |
558 | } | |
559 | } | |
560 | else { | |
561 | self::$selectedLanguages[] = self::$selectedLanguageCode; | |
562 | WCF::getTPL()->assign(array('selectedLanguages' => self::$selectedLanguages)); | |
563 | } | |
564 | ||
565 | WCF::getTPL()->assign(array( | |
566 | 'errorField' => $errorField, | |
567 | 'errorType' => $errorType, | |
1157f8be | 568 | 'availableLanguages' => self::$availableLanguages, |
158bd3ca TD |
569 | 'nextStep' => 'selectLanguages' |
570 | )); | |
571 | WCF::getTPL()->display('stepSelectLanguages'); | |
572 | } | |
573 | ||
574 | /** | |
575 | * Shows the page for configurating the database connection. | |
576 | */ | |
577 | protected function configureDB() { | |
578 | $availableDBClasses = self::getAvailableDBClasses(); | |
579 | $dbHost = 'localhost'; | |
580 | $dbUser = 'root'; | |
581 | $dbPassword = ''; | |
582 | $dbName = 'wcf'; | |
f9600494 | 583 | $dbNumber = 1; |
cdf15dc3 | 584 | $dbClass = ''; |
f9600494 TD |
585 | // set $dbClass to first item in $availableDBClasses |
586 | foreach ($availableDBClasses as $dbClass) { | |
587 | $dbClass = $dbClass['class']; | |
588 | break; | |
589 | } | |
158bd3ca TD |
590 | $overwriteTables = false; |
591 | ||
592 | if (isset($_POST['send'])) { | |
593 | if (isset($_POST['dbHost'])) $dbHost = $_POST['dbHost']; | |
594 | if (isset($_POST['dbUser'])) $dbUser = $_POST['dbUser']; | |
595 | if (isset($_POST['dbPassword'])) $dbPassword = $_POST['dbPassword']; | |
596 | if (isset($_POST['dbName'])) $dbName = $_POST['dbName']; | |
597 | if (isset($_POST['overwriteTables'])) $overwriteTables = intval($_POST['overwriteTables']); | |
598 | // Should the user not be prompted if converted or default n match an | |
599 | // existing installation number? By now the existing installation | |
600 | // will be overwritten just so! | |
f9600494 TD |
601 | |
602 | // ensure that $dbNumber is zero or a positive integer | |
603 | if (isset($_POST['dbNumber'])) $dbNumber = max(0, intval($_POST['dbNumber'])); | |
158bd3ca TD |
604 | if (isset($_POST['dbClass'])) $dbClass = $_POST['dbClass']; |
605 | ||
606 | // get port | |
607 | $dbPort = 0; | |
608 | if (preg_match('/^(.+?):(\d+)$/', $dbHost, $match)) { | |
609 | $dbHost = $match[1]; | |
610 | $dbPort = intval($match[2]); | |
611 | } | |
612 | ||
613 | // test connection | |
614 | try { | |
615 | // check db class | |
616 | $validDB = false; | |
617 | foreach ($availableDBClasses as $dbData) { | |
618 | if ($dbData['class'] == $dbClass) { | |
619 | $validDB = true; | |
620 | break; | |
621 | } | |
622 | } | |
623 | ||
624 | if (!$validDB) { | |
625 | throw new SystemException("Database type '".$dbClass."'. is not available on this system."); | |
626 | } | |
627 | ||
628 | // check connection data | |
629 | $db = new $dbClass($dbHost, $dbUser, $dbPassword, $dbName, $dbPort); | |
630 | $db->connect(); | |
631 | ||
632 | // check sql version | |
633 | if (!empty($availableDBClasses[$dbClass]['minversion'])) { | |
634 | $sqlVersion = $db->getVersion(); | |
635 | if ($sqlVersion != 'unknown') { | |
636 | $compareSQLVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $sqlVersion); | |
637 | if (!(version_compare($compareSQLVersion, $availableDBClasses[$dbClass]['minversion']) >= 0)) { | |
638 | throw new SystemException("Insufficient SQL version '".$compareSQLVersion."'. Version '".$availableDBClasses[$dbClass]['minversion']."' or greater is needed."); | |
639 | } | |
640 | } | |
641 | } | |
642 | ||
643 | // check for table conflicts | |
644 | $conflictedTables = $this->getConflictedTables($db, $dbNumber); | |
76d74665 AE |
645 | if (!empty($conflictedTables) && ($overwriteTables || self::$developerMode)) { |
646 | // remove tables | |
647 | $db->getEditor()->dropConflictedTables($conflictedTables); | |
648 | } | |
158bd3ca TD |
649 | |
650 | // write config.inc | |
651 | if (empty($conflictedTables) || $overwriteTables || self::$developerMode) { | |
652 | // connection successfully established | |
653 | // write configuration to config.inc.php | |
654 | $file = new File(WCF_DIR.'config.inc.php'); | |
655 | $file->write("<?php\n"); | |
656 | $file->write("\$dbHost = '".StringUtil::replace("'", "\\'", $dbHost)."';\n"); | |
657 | $file->write("\$dbPort = ".$dbPort.";\n"); | |
658 | $file->write("\$dbUser = '".StringUtil::replace("'", "\\'", $dbUser)."';\n"); | |
659 | $file->write("\$dbPassword = '".StringUtil::replace("'", "\\'", $dbPassword)."';\n"); | |
660 | $file->write("\$dbName = '".StringUtil::replace("'", "\\'", $dbName)."';\n"); | |
661 | $file->write("\$dbClass = '".StringUtil::replace("'", "\\'", $dbClass)."';\n"); | |
662 | $file->write("if (!defined('WCF_N')) define('WCF_N', $dbNumber);\n?>"); | |
663 | $file->close(); | |
a17de04e | 664 | |
158bd3ca TD |
665 | // go to next step |
666 | $this->gotoNextStep('createDB'); | |
667 | exit; | |
668 | } | |
669 | // show configure temnplate again | |
670 | else { | |
671 | WCF::getTPL()->assign(array('conflictedTables' => $conflictedTables)); | |
672 | } | |
673 | } | |
674 | catch (SystemException $e) { | |
675 | WCF::getTPL()->assign(array('exception' => $e)); | |
676 | } | |
677 | } | |
678 | WCF::getTPL()->assign(array( | |
679 | 'dbHost' => $dbHost, | |
680 | 'dbUser' => $dbUser, | |
681 | 'dbPassword' => $dbPassword, | |
682 | 'dbName' => $dbName, | |
683 | 'dbNumber' => $dbNumber, | |
684 | 'dbClass' => $dbClass, | |
685 | 'availableDBClasses' => $availableDBClasses, | |
686 | 'nextStep' => 'configureDB' | |
687 | )); | |
688 | WCF::getTPL()->display('stepConfigureDB'); | |
689 | } | |
690 | ||
691 | ||
692 | /** | |
693 | * Checks if in the chosen database are tables in conflict with the wcf tables | |
694 | * which will be created in the next step. | |
9f959ced MS |
695 | * |
696 | * @param wcf\system\database\Database $db | |
697 | * @param integer $dbNumber | |
158bd3ca TD |
698 | */ |
699 | protected function getConflictedTables($db, $dbNumber) { | |
700 | // get content of the sql structure file | |
701 | $sql = file_get_contents(TMP_DIR.'setup/db/install.sql'); | |
702 | ||
703 | // installation number value 'n' (WCF_N) must be reflected in the executed sql queries | |
704 | $sql = StringUtil::replace('wcf1_', 'wcf'.$dbNumber.'_', $sql); | |
705 | ||
706 | // get all tablenames which should be created | |
707 | preg_match_all("%CREATE\s+TABLE\s+(\w+)%", $sql, $matches); | |
708 | ||
709 | // get all installed tables from chosen database | |
710 | $existingTables = $db->getEditor()->getTableNames(); | |
711 | ||
712 | // check if existing tables are in conflict with wcf tables | |
713 | $conflictedTables = array(); | |
714 | foreach ($existingTables as $existingTableName) { | |
715 | foreach ($matches[1] as $wcfTableName) { | |
716 | if ($existingTableName == $wcfTableName) { | |
717 | $conflictedTables[] = $wcfTableName; | |
718 | } | |
719 | } | |
720 | } | |
721 | return $conflictedTables; | |
722 | } | |
723 | ||
724 | /** | |
725 | * Creates the database structure of the wcf. | |
726 | */ | |
727 | protected function createDB() { | |
728 | $this->initDB(); | |
729 | ||
730 | // get content of the sql structure file | |
731 | $sql = file_get_contents(TMP_DIR.'setup/db/install.sql'); | |
732 | ||
733 | // installation number value 'n' (WCF_N) must be reflected in the executed sql queries | |
734 | $sql = StringUtil::replace('wcf1_', 'wcf'.WCF_N.'_', $sql); | |
735 | ||
736 | // execute sql queries | |
737 | $parser = new SQLParser($sql); | |
738 | $parser->execute(); | |
739 | ||
740 | // log sql queries | |
741 | preg_match_all("~CREATE\s+TABLE\s+(\w+)~i", $sql, $matches); | |
742 | ||
15fa2802 | 743 | if (!empty($matches[1])) { |
158bd3ca TD |
744 | $sql = "INSERT INTO wcf".WCF_N."_package_installation_sql_log |
745 | (sqlTable) | |
746 | VALUES (?)"; | |
747 | $statement = self::getDB()->prepareStatement($sql); | |
748 | foreach ($matches[1] as $tableName) { | |
749 | $statement->execute(array($tableName)); | |
750 | } | |
751 | } | |
752 | ||
753 | /* | |
754 | * Manually install PIPPackageInstallationPlugin since install.sql content is not escaped resulting | |
755 | * in different behaviour in MySQL and MSSQL. You SHOULD NOT move this into install.sql! | |
756 | */ | |
757 | $sql = "INSERT INTO wcf".WCF_N."_package_installation_plugin | |
758 | (pluginName, priority, className) | |
759 | VALUES (?, ?, ?)"; | |
760 | $statement = self::getDB()->prepareStatement($sql); | |
761 | $statement->execute(array( | |
db92cb8f | 762 | 'packageInstallationPlugin', |
158bd3ca TD |
763 | 1, |
764 | 'wcf\system\package\plugin\PIPPackageInstallationPlugin' | |
765 | )); | |
766 | ||
767 | $this->gotoNextStep('logFiles'); | |
768 | } | |
769 | ||
770 | /** | |
771 | * Logs the unzipped files. | |
772 | */ | |
773 | protected function logFiles() { | |
774 | $this->initDB(); | |
775 | ||
776 | $this->getInstalledFiles(WCF_DIR); | |
777 | $acpTemplateInserts = $fileInserts = array(); | |
778 | foreach (self::$installedFiles as $file) { | |
779 | $match = array(); | |
780 | if (preg_match('!/acp/templates/([^/]+)\.tpl$!', $file, $match)) { | |
781 | // acp template | |
782 | $acpTemplateInserts[] = $match[1]; | |
783 | } | |
784 | else { | |
785 | // regular file | |
786 | $fileInserts[] = StringUtil::replace(WCF_DIR, '', $file); | |
787 | } | |
788 | } | |
789 | ||
790 | // save acp template log | |
791 | if (!empty($acpTemplateInserts)) { | |
792 | $sql = "INSERT INTO wcf".WCF_N."_acp_template | |
793 | (templateName) | |
794 | VALUES (?)"; | |
795 | $statement = self::getDB()->prepareStatement($sql); | |
796 | ||
dcd38d37 | 797 | self::getDB()->beginTransaction(); |
158bd3ca | 798 | foreach ($acpTemplateInserts as $acpTemplate) { |
dcd38d37 | 799 | $statement->executeUnbuffered(array($acpTemplate)); |
158bd3ca | 800 | } |
dcd38d37 | 801 | self::getDB()->commitTransaction(); |
158bd3ca TD |
802 | } |
803 | ||
804 | // save file log | |
805 | if (!empty($fileInserts)) { | |
806 | $sql = "INSERT INTO wcf".WCF_N."_package_installation_file_log | |
807 | (filename) | |
808 | VALUES (?)"; | |
809 | $statement = self::getDB()->prepareStatement($sql); | |
810 | ||
dcd38d37 | 811 | self::getDB()->beginTransaction(); |
158bd3ca | 812 | foreach ($fileInserts as $file) { |
dcd38d37 | 813 | $statement->executeUnbuffered(array($file)); |
158bd3ca | 814 | } |
dcd38d37 | 815 | self::getDB()->commitTransaction(); |
158bd3ca TD |
816 | } |
817 | ||
818 | $this->gotoNextStep('installLanguage'); | |
819 | } | |
820 | ||
821 | /** | |
822 | * Scans the given dir for installed files. | |
9f959ced MS |
823 | * |
824 | * @param string $dir | |
158bd3ca TD |
825 | */ |
826 | protected function getInstalledFiles($dir) { | |
827 | if ($files = glob($dir.'*')) { | |
828 | foreach ($files as $file) { | |
829 | if (is_dir($file)) { | |
830 | $this->getInstalledFiles(FileUtil::addTrailingSlash($file)); | |
831 | } | |
832 | else { | |
833 | self::$installedFiles[] = FileUtil::unifyDirSeperator($file); | |
834 | } | |
835 | } | |
836 | } | |
837 | } | |
838 | ||
839 | /** | |
840 | * Installs the selected languages. | |
841 | */ | |
842 | protected function installLanguage() { | |
843 | $this->initDB(); | |
844 | ||
845 | foreach (self::$selectedLanguages as $language) { | |
846 | // get language.xml file name | |
847 | $filename = TMP_DIR.'install/lang/'.$language.'.xml'; | |
848 | ||
849 | // check the file | |
850 | if (!file_exists($filename)) { | |
4fe0b42b | 851 | throw new SystemException("unable to find language file '".$filename."'"); |
158bd3ca TD |
852 | } |
853 | ||
854 | // open the file | |
855 | $xml = new XML(); | |
856 | $xml->load($filename); | |
857 | ||
858 | // import xml | |
859 | LanguageEditor::importFromXML($xml, 0); | |
860 | } | |
861 | ||
862 | // set default language | |
61022658 AE |
863 | $language = LanguageFactory::getInstance()->getLanguageByCode(in_array(self::$selectedLanguageCode, self::$selectedLanguages) ? self::$selectedLanguageCode : self::$selectedLanguages[0]); |
864 | LanguageFactory::getInstance()->makeDefault($language->languageID); | |
158bd3ca | 865 | |
158bd3ca | 866 | // rebuild language cache |
b401cd0d | 867 | LanguageCacheBuilder::getInstance()->reset(); |
158bd3ca TD |
868 | |
869 | // go to next step | |
870 | $this->gotoNextStep('createUser'); | |
871 | } | |
872 | ||
873 | /** | |
874 | * Shows the page for creating the admin account. | |
875 | */ | |
876 | protected function createUser() { | |
877 | $errorType = $errorField = $username = $email = $confirmEmail = $password = $confirmPassword = ''; | |
878 | ||
879 | $username = ''; | |
880 | $email = $confirmEmail = ''; | |
881 | $password = $confirmPassword = ''; | |
882 | ||
883 | if (isset($_POST['send']) || self::$developerMode) { | |
884 | if (isset($_POST['send'])) { | |
39bea7dd MS |
885 | if (isset($_POST['username'])) $username = StringUtil::trim($_POST['username']); |
886 | if (isset($_POST['email'])) $email = StringUtil::trim($_POST['email']); | |
887 | if (isset($_POST['confirmEmail'])) $confirmEmail = StringUtil::trim($_POST['confirmEmail']); | |
888 | if (isset($_POST['password'])) $password = $_POST['password']; | |
889 | if (isset($_POST['confirmPassword'])) $confirmPassword = $_POST['confirmPassword']; | |
158bd3ca TD |
890 | } |
891 | else { | |
892 | $username = $password = $confirmPassword = 'root'; | |
893 | $email = $confirmEmail = 'woltlab@woltlab.com'; | |
894 | } | |
895 | ||
896 | // error handling | |
897 | try { | |
898 | // username | |
899 | if (empty($username)) { | |
900 | throw new UserInputException('username'); | |
901 | } | |
902 | if (!UserUtil::isValidUsername($username)) { | |
903 | throw new UserInputException('username', 'notValid'); | |
904 | } | |
905 | ||
906 | // e-mail address | |
907 | if (empty($email)) { | |
908 | throw new UserInputException('email'); | |
909 | } | |
910 | if (!UserUtil::isValidEmail($email)) { | |
911 | throw new UserInputException('email', 'notValid'); | |
912 | } | |
913 | ||
914 | // confirm e-mail address | |
915 | if ($email != $confirmEmail) { | |
916 | throw new UserInputException('confirmEmail', 'notEqual'); | |
917 | } | |
918 | ||
919 | // password | |
920 | if (empty($password)) { | |
921 | throw new UserInputException('password'); | |
922 | } | |
923 | ||
924 | // confirm e-mail address | |
925 | if ($password != $confirmPassword) { | |
926 | throw new UserInputException('confirmPassword', 'notEqual'); | |
927 | } | |
928 | ||
929 | // no errors | |
930 | // init database connection | |
931 | $this->initDB(); | |
932 | ||
933 | // get language id | |
934 | $languageID = 0; | |
935 | $sql = "SELECT languageID | |
936 | FROM wcf".WCF_N."_language | |
937 | WHERE languageCode = ?"; | |
938 | $statement = self::getDB()->prepareStatement($sql); | |
939 | $statement->execute(array(self::$selectedLanguageCode)); | |
940 | $row = $statement->fetchArray(); | |
941 | if (isset($row['languageID'])) $languageID = $row['languageID']; | |
942 | ||
943 | // create user | |
944 | $data = array( | |
945 | 'data' => array( | |
946 | 'email' => $email, | |
947 | 'languageID' => $languageID, | |
948 | 'password' => $password, | |
949 | 'username' => $username | |
950 | ), | |
951 | 'groups' => array( | |
952 | 1, | |
953 | 3, | |
954 | 4 | |
955 | ), | |
956 | 'languages' => array( | |
957 | $languageID | |
958 | ) | |
959 | ); | |
960 | ||
961 | $userAction = new UserAction(array(), 'create', $data); | |
962 | $userAction->executeAction(); | |
963 | ||
964 | // go to next step | |
965 | $this->gotoNextStep('installPackages'); | |
966 | exit; | |
967 | } | |
968 | catch (UserInputException $e) { | |
969 | $errorField = $e->getField(); | |
970 | $errorType = $e->getType(); | |
971 | } | |
972 | } | |
973 | ||
974 | WCF::getTPL()->assign(array( | |
975 | 'errorField' => $errorField, | |
976 | 'errorType' => $errorType, | |
977 | 'username' => $username, | |
978 | 'email' => $email, | |
979 | 'confirmEmail' => $confirmEmail, | |
980 | 'password' => $password, | |
981 | 'confirmPassword' => $confirmPassword, | |
982 | 'nextStep' => 'createUser' | |
983 | )); | |
984 | WCF::getTPL()->display('stepCreateUser'); | |
985 | } | |
986 | ||
987 | /** | |
988 | * Registers with wcf setup delivered packages in the package installation queue. | |
989 | */ | |
990 | protected function installPackages() { | |
991 | // init database connection | |
992 | $this->initDB(); | |
993 | ||
994 | // get admin account | |
995 | $admin = new User(1); | |
996 | ||
997 | // get delivered packages | |
998 | $wcfPackageFile = ''; | |
999 | $otherPackages = array(); | |
1000 | $tar = new Tar(SETUP_FILE); | |
1001 | foreach ($tar->getContentList() as $file) { | |
1002 | if ($file['type'] != 'folder' && StringUtil::indexOf($file['filename'], 'install/packages/') === 0) { | |
1003 | $packageFile = basename($file['filename']); | |
158bd3ca | 1004 | |
1d9fd26a AE |
1005 | // ignore any files which aren't an archive |
1006 | if (preg_match('~\.(tar\.gz|tgz|tar)$~', $packageFile)) { | |
1007 | $packageName = preg_replace('!\.(tar\.gz|tgz|tar)$!', '', $packageFile); | |
1008 | ||
1009 | if ($packageName == 'com.woltlab.wcf') { | |
1010 | $wcfPackageFile = $packageFile; | |
1011 | } | |
1012 | else { | |
1013 | $isStrato = (!empty($_SERVER['DOCUMENT_ROOT']) && (strpos($_SERVER['DOCUMENT_ROOT'], 'strato') !== false)); | |
1014 | if (!$isStrato && preg_match('!\.(tar\.gz|tgz)$!', $packageFile)) { | |
1015 | // try to unzip zipped package files | |
1016 | if (FileUtil::uncompressFile(TMP_DIR.'install/packages/'.$packageFile, TMP_DIR.'install/packages/'.$packageName.'.tar')) { | |
1017 | @unlink(TMP_DIR.'install/packages/'.$packageFile); | |
1018 | $packageFile = $packageName.'.tar'; | |
1019 | } | |
158bd3ca | 1020 | } |
1d9fd26a AE |
1021 | |
1022 | $otherPackages[$packageName] = $packageFile; | |
158bd3ca | 1023 | } |
158bd3ca TD |
1024 | } |
1025 | } | |
1026 | } | |
1027 | $tar->close(); | |
1028 | ||
1029 | // register packages in queue | |
1030 | // get new process id | |
1031 | $sql = "SELECT MAX(processNo) AS processNo | |
1032 | FROM wcf".WCF_N."_package_installation_queue"; | |
1033 | $statement = self::getDB()->prepareStatement($sql); | |
1034 | $statement->execute(); | |
1035 | $result = $statement->fetchArray(); | |
1036 | $processNo = intval($result['processNo']) + 1; | |
158bd3ca TD |
1037 | |
1038 | // search existing wcf package | |
1039 | $sql = "SELECT COUNT(*) AS count | |
1040 | FROM wcf".WCF_N."_package | |
1041 | WHERE package = 'com.woltlab.wcf'"; | |
1042 | $statement = self::getDB()->prepareStatement($sql); | |
1043 | $statement->execute(); | |
1044 | $row = $statement->fetchArray(); | |
1045 | if (!$row['count']) { | |
1046 | if (empty($wcfPackageFile)) { | |
4fe0b42b | 1047 | throw new SystemException('the essential package com.woltlab.wcf is missing.'); |
158bd3ca TD |
1048 | } |
1049 | ||
1050 | // register essential wcf package | |
89142da9 | 1051 | $queue = PackageInstallationQueueEditor::create(array( |
f287c18d AE |
1052 | 'processNo' => $processNo, |
1053 | 'userID' => $admin->userID, | |
d7281d46 AE |
1054 | 'package' => 'com.woltlab.wcf', |
1055 | 'packageName' => 'WoltLab Community Framework', | |
158bd3ca | 1056 | 'archive' => TMP_DIR.'install/packages/'.$wcfPackageFile |
89142da9 | 1057 | )); |
158bd3ca TD |
1058 | } |
1059 | ||
1060 | // register all other delivered packages | |
1061 | asort($otherPackages); | |
1062 | foreach ($otherPackages as $packageName => $packageFile) { | |
d7281d46 AE |
1063 | // extract packageName from archive's package.xml |
1064 | $archive = new PackageArchive(TMP_DIR.'install/packages/'.$packageFile); | |
1065 | try { | |
1066 | $archive->openArchive(); | |
1067 | } | |
1068 | catch (\Exception $e) { | |
8e2c12f5 AE |
1069 | // we've encountered a broken archive, revert everything and then fail |
1070 | $sql = "SELECT queueID, parentQueueID | |
1071 | FROM wcf".WCF_N."_package_installation_queue"; | |
1072 | $statement = WCF::getDB()->prepareStatement($sql); | |
1073 | $statement->execute(); | |
1074 | $queues = array(); | |
1075 | while ($row = $statement->fetchArray()) { | |
1076 | $queues[$row['queueID']] = $row['parentQueueID']; | |
1077 | } | |
1078 | ||
1079 | $queueIDs = array(); | |
1080 | $queueID = $queue->queueID; | |
1081 | while ($queueID) { | |
1082 | $queueIDs[] = $queueID; | |
1083 | ||
1084 | $queueID = (isset($queues[$queueID])) ?: 0; | |
1085 | } | |
1086 | ||
1087 | // remove previously created queues | |
1088 | if (!empty($queueIDs)) { | |
1089 | $sql = "DELETE FROM wcf".WCF_N."_package_installation_queue | |
1090 | WHERE queueID = ?"; | |
1091 | $statement = WCF::getDB()->prepareStatement($sql); | |
1092 | WCF::getDB()->beginTransaction(); | |
1093 | foreach ($queueIDs as $queueID) { | |
1094 | $statement->execute(array($queueID)); | |
1095 | } | |
1096 | WCF::getDB()->commitTransaction(); | |
1097 | } | |
1098 | ||
1099 | // remove package files | |
1100 | @unlink(TMP_DIR.'install/packages/'.$wcfPackageFile); | |
1101 | foreach ($otherPackages as $packageFile) { | |
1102 | @unlink(TMP_DIR.'install/packages/'.$packageFile); | |
1103 | } | |
1104 | ||
1105 | // throw exception again | |
1106 | throw new SystemException('', 0, '', $e); | |
d7281d46 AE |
1107 | } |
1108 | ||
89142da9 AE |
1109 | $queue = PackageInstallationQueueEditor::create(array( |
1110 | 'parentQueueID' => $queue->queueID, | |
f287c18d AE |
1111 | 'processNo' => $processNo, |
1112 | 'userID' => $admin->userID, | |
d7281d46 | 1113 | 'package' => $packageName, |
a2ad7897 | 1114 | 'packageName' => $archive->getLocalizedPackageInfo('packageName'), |
158bd3ca | 1115 | 'archive' => TMP_DIR.'install/packages/'.$packageFile |
89142da9 | 1116 | )); |
158bd3ca TD |
1117 | } |
1118 | ||
1119 | // login as admin | |
1120 | $factory = new ACPSessionFactory(); | |
1121 | $factory->load(); | |
1122 | ||
1123 | SessionHandler::getInstance()->changeUser($admin); | |
1124 | SessionHandler::getInstance()->register('masterPassword', 1); | |
1125 | SessionHandler::getInstance()->update(); | |
1126 | ||
158bd3ca | 1127 | $installPhpDeleted = @unlink('./install.php'); |
a17de04e | 1128 | @unlink('./test.php'); |
158bd3ca TD |
1129 | $wcfSetupTarDeleted = @unlink('./WCFSetup.tar.gz'); |
1130 | ||
1131 | // print page | |
1132 | WCF::getTPL()->assign(array( | |
1133 | 'installPhpDeleted' => $installPhpDeleted, | |
1134 | 'wcfSetupTarDeleted' => $wcfSetupTarDeleted | |
1135 | )); | |
1136 | WCF::getTPL()->display('stepInstallPackages'); | |
1137 | ||
1138 | // delete tmp files | |
364a2e49 | 1139 | $directory = TMP_DIR.'/'; |
ac9b0f6e | 1140 | DirectoryUtil::getInstance($directory)->removePattern(new Regex('\.tar(\.gz)?$'), true); |
158bd3ca TD |
1141 | } |
1142 | ||
1143 | /** | |
1144 | * Goes to the next step. | |
9f959ced | 1145 | * |
158bd3ca TD |
1146 | * @param string $nextStep |
1147 | */ | |
1148 | protected function gotoNextStep($nextStep) { | |
1149 | WCF::getTPL()->assign(array('nextStep' => $nextStep)); | |
1150 | WCF::getTPL()->display('stepNext'); | |
1151 | } | |
1152 | ||
1153 | /** | |
1154 | * Installs the files of the tar archive. | |
1155 | */ | |
1156 | protected static function installFiles() { | |
1157 | new Installer(self::$wcfDir, SETUP_FILE, null, 'install/files/'); | |
1158 | } | |
1159 | ||
1160 | /** | |
aac1247e | 1161 | * Gets the package name of the first application in WCFSetup.tar.gz. |
158bd3ca TD |
1162 | */ |
1163 | protected static function getPackageName() { | |
1164 | // get package name | |
1165 | $tar = new Tar(SETUP_FILE); | |
1166 | foreach ($tar->getContentList() as $file) { | |
1167 | if ($file['type'] != 'folder' && StringUtil::indexOf($file['filename'], 'install/packages/') === 0) { | |
1168 | $packageFile = basename($file['filename']); | |
1169 | $packageName = preg_replace('!\.(tar\.gz|tgz|tar)$!', '', $packageFile); | |
1170 | ||
1171 | if ($packageName != 'com.woltlab.wcf') { | |
1172 | try { | |
1173 | $archive = new PackageArchive(TMP_DIR.'install/packages/'.$packageFile); | |
1174 | $archive->openArchive(); | |
a2ad7897 | 1175 | self::$setupPackageName = $archive->getLocalizedPackageInfo('packageName'); |
158bd3ca TD |
1176 | $archive->getTar()->close(); |
1177 | break; | |
1178 | } | |
1179 | catch (SystemException $e) {} | |
1180 | } | |
1181 | } | |
1182 | } | |
1183 | $tar->close(); | |
1184 | ||
1185 | // assign package name | |
1186 | WCF::getTPL()->assign(array('setupPackageName' => self::$setupPackageName)); | |
1187 | } | |
1188 | } |