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