Merge branch 'master' of github.com:WoltLab/WCF
[GitHub/WoltLab/WCF.git] / wcfsetup / install.php
CommitLineData
158bd3ca
TD
1<?php
2/**
3 * This script tries to find the temp folder and unzip all setup files into.
4 *
5 * @author Marcel Werk
6 * @copyright 2001-2011 WoltLab GmbH
7 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
8 */
9// define constants
10define('INSTALL_SCRIPT_DIR', dirname(__FILE__).'/');
11define('SETUP_FILE', INSTALL_SCRIPT_DIR . 'WCFSetup.tar.gz');
12define('NO_IMPORTS', 1);
13
14// set exception handler
15set_exception_handler('handleException');
16// set php error handler
17set_error_handler('handleError', E_ALL);
18
19// define list of needed file
20$neededFilesPattern = array(
21 '!^setup/.*!',
7da7f7cc 22 '!^install/files/acp/images/wcfLogo.*!',
e94c3830 23 '!^install/files/acp/style/setup/.*!',
158bd3ca 24 '!^install/files/lib/data/.*!',
7da7f7cc 25 '!^install/files/icon/.*!',
e2a34399 26 '!^install/files/font/.*!',
158bd3ca
TD
27 '!^install/files/lib/system/.*!',
28 '!^install/files/lib/util/.*!',
158bd3ca
TD
29 '!^install/lang/.*!',
30 '!^install/packages/.*!');
31
32// define needed functions and classes
33/**
34 * WCF::handleException() calls the show method on exceptions that implement this interface.
35 *
36 * @package com.woltlab.wcf.system.exception
37 * @author Marcel Werk
38 */
39interface IPrintableException {
40 public function show();
41}
42
43// define needed classes
44// needed are:
45// SystemException, PrintableException, BasicFileUtil, Tar, File, ZipFile
46/**
47 * A SystemException is thrown when an unexpected error occurs.
48 *
49 * @package com.woltlab.wcf.system.exception
50 * @author Marcel Werk
51 */
52class SystemException extends \Exception implements IPrintableException {
53 protected $description;
54 protected $information = '';
55 protected $functions = '';
56
57 /**
58 * Creates a new SystemException.
59 *
60 * @param message string error message
61 * @param code integer error code
62 * @param description string description of the error
63 */
64 public function __construct($message = '', $code = 0, $description = '') {
65 parent::__construct($message, $code);
66 $this->description = $description;
67 }
68
69 /**
70 * Returns the description of this exception.
71 *
39bea7dd 72 * @return string
158bd3ca
TD
73 */
74 public function getDescription() {
75 return $this->description;
76 }
77
78 /**
79 * Prints this exception.
80 * This method is called by WCF::handleException().
81 */
82 public function show() {
83 ?>
84<html>
85<head>
86<title>Fatal error: <?php echo htmlspecialchars($this->getMessage()); ?></title>
158bd3ca 87
53e00c6b
L
88<style type="text/css">
89 body {
90 font-family: Verdana, Helvetica, sans-serif;
91 font-size: 0.8em;
92 }
93 div {
94 border: 1px outset lightgrey;
95 padding: 3px;
96 background-color: lightgrey;
97 }
98
99 div div {
100 border: 1px inset lightgrey;
101 padding: 4px;
102 }
103
104 h1 {
105 background-color: #154268;
106 padding: 4px;
107 color: #fff;
108 margin: 0 0 3px 0;
109 font-size: 1.15em;
110 }
111 h2 {
112 font-size: 1.1em;
113 margin-bottom: 0;
114 }
115
116 pre, p {
117 margin: 0;
118 }
158bd3ca
TD
119</style>
120</head>
53e00c6b 121
158bd3ca
TD
122<body>
123 <div>
124 <h1>Fatal error: <?php echo htmlspecialchars($this->getMessage()); ?></h1>
125
126 <div>
127 <p><?php echo $this->getDescription(); ?></p>
128 <?php if ($this->getCode()) { ?><p>You get more information about the problem in our knowledge base: <a href="http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?>">http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?></a></p><?php } ?>
129
130 <h2>Information:</h2>
131 <p>
132 <b>error message:</b> <?php echo htmlspecialchars($this->getMessage()); ?><br />
133 <b>error code:</b> <?php echo intval($this->getCode()); ?><br />
134 <?php echo $this->information; ?>
135 <b>file:</b> <?php echo htmlspecialchars($this->getFile()); ?> (<?php echo $this->getLine(); ?>)<br />
136 <b>php version:</b> <?php echo htmlspecialchars(phpversion()); ?><br />
137 <b>wcf version:</b> <?php if (defined('WCF_VERSION')) echo WCF_VERSION; ?><br />
138 <b>date:</b> <?php echo gmdate('r'); ?><br />
139 <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo htmlspecialchars($_SERVER['REQUEST_URI']); ?><br />
140 <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo htmlspecialchars($_SERVER['HTTP_REFERER']); ?><br />
141 </p>
142
143 <h2>Stacktrace:</h2>
144 <pre><?php echo htmlspecialchars($this->getTraceAsString()); ?></pre>
145 </div>
146
147 <?php echo $this->functions; ?>
148 </div>
149</body>
150</html>
151
152<?php
153 }
154}
155
156
157/**
158 * Loads the required classes automatically.
159 */
160function __autoload($className) {
161 $namespaces = explode('\\', $className);
162 if (count($namespaces) > 1) {
163 // remove 'wcf' component
164 array_shift($namespaces);
165
166 $className = implode('/', $namespaces);
01bd2eff 167 $classPath = TMP_DIR . 'install/files/lib/' . $className . '.class.php';
158bd3ca
TD
168 if (file_exists($classPath)) {
169 require_once($classPath);
170 }
171 }
172}
173
174/**
175 * Escapes strings for execution in sql queries.
176 */
177function escapeString($string) {
178 return \wcf\system\WCF::getDB()->escapeString($string);
179}
180
181/**
182 * Calls the show method on the given exception.
183 *
184 * @param Exception $e
185 */
186function handleException(\Exception $e) {
187 if ($e instanceof IPrintableException || $e instanceof \wcf\system\exception\IPrintableException) {
188 $e->show();
189 exit;
190 }
191
192 print $e;
193}
194
195/**
196 * Catches php errors and throws instead a system exception.
197 *
198 * @param integer $errorNo
199 * @param string $message
200 * @param string $filename
201 * @param integer $lineNo
202 */
203function handleError($errorNo, $message, $filename, $lineNo) {
204 if (error_reporting() != 0) {
205 $type = 'error';
206 switch ($errorNo) {
207 case 2: $type = 'warning';
208 break;
209 case 8: $type = 'notice';
210 break;
211 }
212
213 throw new SystemException('PHP '.$type.' in file '.$filename.' ('.$lineNo.'): '.$message, 0);
214 }
215}
216
217/**
218 * BasicFileUtil contains file-related functions.
219 *
39bea7dd 220 * @package com.woltlab.wcf.util
158bd3ca
TD
221 * @author Marcel Werk
222 */
223class BasicFileUtil {
224 /**
225 * Tries to find the temp folder.
226 *
227 * @return string
228 */
229 public static function getTempFolder() {
230 $tmpDirName = TMP_FILE_PREFIX.'/';
231
232 // use tmp folder in document root by default
233 if (!empty($_SERVER['DOCUMENT_ROOT'])) {
234 if (!@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName)) {
235 @mkdir($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName, 0777, true);
1232bce2 236 self::makeWritable($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName);
158bd3ca
TD
237 }
238
239 if (@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName) && @is_writable($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName)) {
240 return $_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName;
241 }
242 }
243
244 foreach (array('TMP', 'TEMP', 'TMPDIR') as $tmpDir) {
245 if (isset($_ENV[$tmpDir]) && @is_writable($_ENV[$tmpDir])) {
246 $dir = $_ENV[$tmpDir] . '/' . $tmpDirName;
247 @mkdir($dir, 0777);
1232bce2 248 self::makeWritable($dir);
158bd3ca
TD
249
250 if (@file_exists($dir) && @is_writable($dir)) {
251 return $dir;
252 }
253 }
254 }
255
256 $dir = INSTALL_SCRIPT_DIR . 'tmp/' . $tmpDirName;
257 @mkdir($dir, 0777);
1232bce2 258 self::makeWritable($dir);
158bd3ca
TD
259
260 if (!@file_exists($dir) || !@is_writable($dir)) {
261 $tmpDir = explode('/', $dir);
262 array_pop($tmpDir);
263 $dir = implode('/', $tmpDir);
264
4fe0b42b 265 throw new SystemException('There is no access to the system temporary folder due to an unknown reason and no user specific temporary folder exists in '.INSTALL_SCRIPT_DIR.'! This is a misconfiguration of your webserver software! Please create a folder called '.$dir.' using your favorite ftp program, make it writable and then retry this installation.');
158bd3ca
TD
266 }
267
268 return $dir;
269 }
1232bce2
AE
270
271 /**
272 * Tries to make a file or directory writable. It starts of with the least
273 * permissions and goes up until 0777.
274 *
275 * @param string $filename
276 */
277 public static function makeWritable($filename) {
278 if (is_writable($filename)) {
279 return;
280 }
281
282 $chmods = array('0644', '0755', '0775', '0777');
283
284 $startIndex = 0;
285 if (is_dir($filename)) {
286 $startIndex = 1;
287 }
288
289 for ($i = $startIndex; $i < 4; $i++) {
290 @chmod($filename, octdec($chmods[$i]));
291
292 if (is_writable($filename)) {
293 break;
294 }
295 else if ($i == 3) {
296 // does not work with 0777
297 throw new SystemException("Unable to make '".$filename."' writable. This is a misconfiguration of your server, please contact your system administrator or hosting provider.");
298 }
299 }
300 }
158bd3ca
TD
301}
302
303/**
304 * Opens tar or tar.gz archives.
305 *
306 * Usage:
307 * ------
308 * $tar = new Tar('archive.tar');
309 * $contentList = $tar->getContentList();
310 * foreach ($contentList as $key => $val) {
311 * $tar->extract($key, DESTINATION);
312 * }
313 */
314class Tar {
315 protected $archiveName = '';
316 protected $contentList = array();
317 protected $opened = false;
318 protected $read = false;
319 protected $file = null;
320 protected $isZipped = false;
321 protected $mode = 'rb';
322
323 /**
324 * Creates a new Tar object.
325 * archiveName must be tarball or gzipped tarball
326 *
39bea7dd 327 * @param string $archiveName
158bd3ca
TD
328 */
329 public function __construct($archiveName) {
158bd3ca 330 if (!is_file($archiveName)) {
4fe0b42b 331 throw new SystemException("unable to find tar archive '".$archiveName."'");
158bd3ca
TD
332 }
333
334 $this->archiveName = $archiveName;
335 $this->open();
336 $this->readContent();
337 }
338
339 /**
340 * Destructor of this class, closes tar archive.
341 */
342 public function __destruct() {
343 $this->close();
344 }
345
346 /**
347 * Opens the tar archive and stores filehandle.
348 */
349 public function open() {
350 if (!$this->opened) {
351 if ($this->isZipped) $this->file = new ZipFile($this->archiveName, $this->mode);
352 else {
353 // test compression
354 $this->file = new File($this->archiveName, $this->mode);
355 if ($this->file->read(2) == "\37\213") {
356 $this->file->close();
357 $this->isZipped = true;
358 $this->file = new ZipFile($this->archiveName, $this->mode);
359 }
360 else {
361 $this->file->seek(0);
362 }
363 }
364 $this->opened = true;
365 }
366 }
367
368 /**
369 * Closes the opened file.
370 */
371 public function close() {
372 if ($this->opened) {
373 $this->file->close();
374 $this->opened = false;
375 }
376 }
377
378 /**
379 * Returns the table of contents (TOC) list for this tar archive.
380 *
39bea7dd 381 * @return array list of content
158bd3ca
TD
382 */
383 public function getContentList() {
384 if (!$this->read) {
385 $this->open();
386 $this->readContent();
387 }
388 return $this->contentList;
389 }
390
391 /**
392 * Returns an associative array with information
393 * about a specific file in the archive.
394 *
39bea7dd
MS
395 * @param mixed $fileindex index or name of the requested file
396 * @return array $fileInfo
158bd3ca
TD
397 */
398 public function getFileInfo($fileIndex) {
399 if (!is_int($fileIndex)) {
400 $fileIndex = $this->getIndexByFilename($fileIndex);
401 }
402
403 if (!isset($this->contentList[$fileIndex])) {
6286572b 404 throw new SystemException("Tar: could find file '".$fileIndex."' in archive");
158bd3ca
TD
405 }
406 return $this->contentList[$fileIndex];
407 }
408
409 /**
410 * Searchs a file in the tar archive
411 * and returns the numeric fileindex.
412 * Returns false if not found.
413 *
39bea7dd
MS
414 * @param string $filename
415 * @return integer index of the requested file
158bd3ca
TD
416 */
417 public function getIndexByFilename($filename) {
418 foreach ($this->contentList as $index => $file) {
419 if ($file['filename'] == $filename) {
420 return $index;
421 }
422 }
423 return false;
424 }
425
426 /**
427 * Extracts a specific file and returns the content as string.
428 * Returns false if extraction failed.
429 *
39bea7dd
MS
430 * @param mixed $index index or name of the requested file
431 * @return string content of the requested file
158bd3ca
TD
432 */
433 public function extractToString($index) {
434 if (!$this->read) {
435 $this->open();
436 $this->readContent();
437 }
438 $header = $this->getFileInfo($index);
439
440 // can not extract a folder
441 if ($header['type'] != 'file') {
442 return false;
443 }
444
445 // seek to offset
446 $this->file->seek($header['offset']);
447
448 // read data
449 $content = '';
450 $n = floor($header['size'] / 512);
451 for($i = 0; $i < $n; $i++) {
452 $content .= $this->file->read(512);
453 }
454 if(($header['size'] % 512) != 0) {
455 $buffer = $this->file->read(512);
456 $content .= substr($buffer, 0, ($header['size'] % 512));
457 }
458
459 return $content;
460 }
461
462 /**
463 * Extracts a specific file and writes it's content
464 * to the file specified with $destination.
465 *
39bea7dd
MS
466 * @param mixed $index index or name of the requested file
467 * @param string $destination
468 * @return boolean $success
158bd3ca
TD
469 */
470 public function extract($index, $destination) {
471 if (!$this->read) {
472 $this->open();
473 $this->readContent();
474 }
475 $header = $this->getFileInfo($index);
476
477 // can not extract a folder
478 if ($header['type'] != 'file') {
479 return false;
480 }
481
482 // seek to offset
483 $this->file->seek($header['offset']);
484
485 $targetFile = new File($destination);
486
487 // read data
488 $n = floor($header['size'] / 512);
489 for ($i = 0; $i < $n; $i++) {
490 $content = $this->file->read(512);
491 $targetFile->write($content, 512);
492 }
493 if (($header['size'] % 512) != 0) {
494 $content = $this->file->read(512);
495 $targetFile->write($content, ($header['size'] % 512));
496 }
497
498 $targetFile->close();
1232bce2 499 BasicFileUtil::makeWritable($destination);
158bd3ca
TD
500
501 if ($header['mtime']) {
502 @$targetFile->touch($header['mtime']);
503 }
504
505 // check filesize
506 if (filesize($destination) != $header['size']) {
4fe0b42b 507 throw new SystemException("Could not untar file '".$header['filename']."' to '".$destination."'. Maybe disk quota exceeded in folder '".dirname($destination)."'.");
158bd3ca
TD
508 }
509
510 return true;
511 }
512
513 /**
514 * Reads table of contents (TOC) from tar archive.
515 * This does not get the entire to memory but only parts of it.
516 */
517 protected function readContent() {
518 $this->contentList = array();
519 $this->read = true;
520 $i = 0;
521
522 // Read the 512 bytes header
523 while (strlen($binaryData = $this->file->read(512)) != 0) {
524 // read header
525 $header = $this->readHeader($binaryData);
526 if ($header === false) {
527 continue;
528 }
529 $this->contentList[$i] = $header;
530 $this->contentList[$i]['index'] = $i;
531 $i++;
532
533 $this->file->seek($this->file->tell() + (512 * ceil(($header['size'] / 512))));
534 }
535 }
536
537 /**
538 * Unpacks file header for one file entry.
539 *
39bea7dd
MS
540 * @param string $binaryData
541 * @return array $fileheader
158bd3ca
TD
542 */
543 protected function readHeader($binaryData) {
544 if (strlen($binaryData) != 512) {
545 return false;
546 }
547
548 $header = array();
549 $checksum = 0;
550 // First part of the header
551 for ($i = 0; $i < 148; $i++) {
552 $checksum += ord(substr($binaryData, $i, 1));
553 }
554 // Calculate the checksum
555 // Ignore the checksum value and replace it by ' ' (space)
556 for ($i = 148; $i < 156; $i++) {
557 $checksum += ord(' ');
558 }
559 // Last part of the header
560 for ($i = 156; $i < 512; $i++) {
561 $checksum += ord(substr($binaryData, $i, 1));
562 }
563
564 // Extract the values
565 //$data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $binaryData);
566 $data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $binaryData);
567
568 // Extract the properties
569 $header['checksum'] = octDec(trim($data['checksum']));
570 if ($header['checksum'] == $checksum) {
571 $header['filename'] = trim($data['filename']);
572 $header['mode'] = octDec(trim($data['mode']));
573 $header['uid'] = octDec(trim($data['uid']));
574 $header['gid'] = octDec(trim($data['gid']));
575 $header['size'] = octDec(trim($data['size']));
576 $header['mtime'] = octDec(trim($data['mtime']));
577 $header['prefix'] = trim($data['prefix']);
578 if ($header['prefix']) {
579 $header['filename'] = $header['prefix'].'/'.$header['filename'];
580 }
581 if (($header['typeflag'] = $data['typeflag']) == '5') {
582 $header['size'] = 0;
583 $header['type'] = 'folder';
584 }
585 else {
586 $header['type'] = 'file';
587 }
588 $header['offset'] = $this->file->tell();
589
590 return $header;
591 }
592 else {
593 return false;
594 }
595 }
596}
597
598/**
599 * The File class handles all file operations.
600 *
601 * Example:
602 * using php functions:
603 * $fp = fopen('filename', 'wb');
604 * fwrite($fp, '...');
605 * fclose($fp);
606 *
607 * using this class:
608 * $file = new File('filename');
609 * $file->write('...');
610 * $file->close();
611 *
612 * @author Marcel Werk
613 */
614class File {
615 protected $resource = null;
616 protected $filename;
617
618 /**
619 * Opens a new file.
620 *
39bea7dd
MS
621 * @param string $filename
622 * @param string $mode
158bd3ca
TD
623 */
624 public function __construct($filename, $mode = 'wb') {
625 $this->filename = $filename;
626 $this->resource = fopen($filename, $mode);
627 if ($this->resource === false) {
4fe0b42b 628 throw new SystemException('Can not open file ' . $filename);
158bd3ca
TD
629 }
630 }
631
632 /**
633 * Calls the specified function on the open file.
634 * Do not call this function directly. Use $file->write('') instead.
635 *
39bea7dd
MS
636 * @param string $function
637 * @param array $arguments
158bd3ca
TD
638 */
639 public function __call($function, $arguments) {
640 if (function_exists('f' . $function)) {
641 array_unshift($arguments, $this->resource);
39bea7dd 642 return call_user_func_array('f' . $function, $arguments);
158bd3ca
TD
643 }
644 else if (function_exists($function)) {
645 array_unshift($arguments, $this->filename);
39bea7dd 646 return call_user_func_array($function, $arguments);
158bd3ca
TD
647 }
648 else {
4fe0b42b 649 throw new SystemException('Can not call file method ' . $function);
158bd3ca
TD
650 }
651 }
652}
653
654/**
655 * The File class handles all file operations on a zipped file.
656 *
657 * @author Marcel Werk
658 */
659class ZipFile extends File {
660 /**
661 * Opens a new zipped file.
662 *
39bea7dd
MS
663 * @param string $filename
664 * @param string $mode
158bd3ca
TD
665 */
666 public function __construct($filename, $mode = 'wb') {
667 $this->filename = $filename;
668 if (!function_exists('gzopen')) {
4fe0b42b 669 throw new SystemException('Can not find functions of the zlib extension');
158bd3ca
TD
670 }
671 $this->resource = @gzopen($filename, $mode);
672 if ($this->resource === false) {
4fe0b42b 673 throw new SystemException('Can not open file ' . $filename);
158bd3ca
TD
674 }
675 }
676
677 /**
678 * Calls the specified function on the open file.
679 *
39bea7dd
MS
680 * @param string $function
681 * @param array $arguments
158bd3ca
TD
682 */
683 public function __call($function, $arguments) {
684 if (function_exists('gz' . $function)) {
685 array_unshift($arguments, $this->resource);
39bea7dd 686 return call_user_func_array('gz' . $function, $arguments);
158bd3ca
TD
687 }
688 else if (function_exists($function)) {
689 array_unshift($arguments, $this->filename);
39bea7dd 690 return call_user_func_array($function, $arguments);
158bd3ca
TD
691 }
692 else {
4fe0b42b 693 throw new SystemException('Can not call method ' . $function);
158bd3ca
TD
694 }
695 }
696
697 /**
698 * Returns the filesize of the unzipped file
699 */
700 public function getFileSize() {
701 $byteBlock = 1<<14;
702 $eof = $byteBlock;
703
704 // the correction is for zip files that are too small
705 // to get in the first while loop
706 $correction = 1;
707 while ($this->seek($eof) == 0) {
708 $eof += $byteBlock;
709 $correction = 0;
710 }
711
712 while ($byteBlock > 1) {
713 $byteBlock >>= 1;
714 $eof += $byteBlock * ($this->seek($eof) ? -1 : 1);
715 }
716
717 if ($this->seek($eof) == -1) $eof -= 1;
718
719 $this->rewind();
720 return $eof - $correction;
721 }
722}
723
724// let's go
725// get temp file prefix
726if (isset($_REQUEST['tmpFilePrefix'])) {
727 $prefix = preg_replace('/[^a-f0-9_]+/', '', $_REQUEST['tmpFilePrefix']);
728}
729else {
730 $prefix = substr(sha1(uniqid(microtime())), 0, 8);
731}
732define('TMP_FILE_PREFIX', $prefix);
733
734// try to find the temp folder
735define('TMP_DIR', BasicFileUtil::getTempFolder());
736
7da7f7cc
AE
737/**
738 * Reads a file resource from temp folder.
739 *
740 * @param string $key
741 * @param string $directory
742 */
743function readFileResource($key, $directory) {
ec6e78b9 744 if (preg_match('~[\w\-]+\.(css|jpg|png|svg|eot|woff|ttf)~', $_GET[$key], $match)) {
7da7f7cc
AE
745 switch ($match[1]) {
746 case 'css':
747 header('Content-Type: text/css');
748 break;
749
750 case 'jpg':
751 header('Content-Type: image/jpg');
752 break;
753
754 case 'png':
755 header('Content-Type: image/png');
756 break;
757
758 case 'svg':
759 header('Content-Type: image/svg+xml');
760 break;
ec6e78b9
MW
761
762 case 'eot':
763 header('Content-Type: application/vnd.ms-fontobject');
764 break;
765
766 case 'woff':
767 header('Content-Type: application/font-woff');
768 break;
769
770 case 'ttf':
771 header('Content-Type: application/octet-stream');
772 break;
7da7f7cc
AE
773 }
774
2d9861cd
AE
775 header('Expires: '.gmdate('D, d M Y H:i:s', time() + 3600).' GMT');
776 header('Last-Modified: Mon, 26 Jul 1997 05:00:00 GMT');
777 header('Cache-Control: public, max-age=3600');
778
7da7f7cc 779 readfile($directory . $_GET[$key]);
158bd3ca
TD
780 }
781 exit;
782}
783
7da7f7cc
AE
784// show image from temp folder
785if (isset($_GET['showImage'])) {
786 readFileResource('showImage', TMP_DIR . 'install/files/acp/images/');
787}
788// show icon from temp folder
789if (isset($_GET['showIcon'])) {
790 readFileResource('showIcon', TMP_DIR . 'install/files/icon/');
791}
792// show css from temp folder
793if (isset($_GET['showCSS'])) {
e94c3830 794 readFileResource('showCSS', TMP_DIR . 'install/files/acp/style/setup/');
7da7f7cc 795}
ec6e78b9
MW
796// show fonts from temp folder
797if (isset($_GET['showFont'])) {
798 readFileResource('showFont', TMP_DIR . 'install/files/font/');
799}
7da7f7cc 800
53e00c6b 801// check whether setup files are already unzipped
158bd3ca
TD
802if (!file_exists(TMP_DIR . 'install/files/lib/system/WCFSetup.class.php')) {
803 // try to unzip all setup files into temp folder
804 $tar = new Tar(SETUP_FILE);
805 $contentList = $tar->getContentList();
15fa2802 806 if (empty($contentList)) {
4fe0b42b 807 throw new SystemException("Can not unpack 'WCFSetup.tar.gz'. File is probably broken.");
158bd3ca
TD
808 }
809
810 foreach ($contentList as $file) {
811 foreach ($neededFilesPattern as $pattern) {
812 if (preg_match($pattern, $file['filename'])) {
813 // create directory if not exists
814 $dir = TMP_DIR . dirname($file['filename']);
815 if (!@is_dir($dir)) {
816 @mkdir($dir, 0777, true);
1232bce2 817 BasicFileUtil::makeWritable($dir);
158bd3ca
TD
818 }
819
820 $tar->extract($file['index'], TMP_DIR . $file['filename']);
821 }
822 }
823 }
824 $tar->close();
825
826 // create cache folders
827 @mkdir(TMP_DIR . 'setup/lang/cache/', 0777);
1232bce2 828 BasicFileUtil::makeWritable(TMP_DIR . 'setup/lang/cache/');
158bd3ca
TD
829
830 @mkdir(TMP_DIR . 'setup/template/compiled/', 0777);
1232bce2 831 BasicFileUtil::makeWritable(TMP_DIR . 'setup/template/compiled/');
158bd3ca
TD
832}
833
834if (!class_exists('wcf\system\WCFSetup')) {
4fe0b42b 835 throw new SystemException("Can not find class 'WCFSetup'");
158bd3ca
TD
836}
837
838// start setup
dcb3a44c 839new \wcf\system\WCFSetup();