/wcfsetup/install/files/lib/system/setup/Installer.class.php

https://github.com/KomHunter2/WCF · PHP · 189 lines · 107 code · 18 blank · 64 comment · 25 complexity · a181a03637795353f103846149555ade MD5 · raw file

  1. <?php
  2. namespace wcf\system\setup;
  3. use wcf\system\exception\SystemException;
  4. use wcf\system\io\Tar;
  5. use wcf\util\FileUtil;
  6. use wcf\util\StringUtil;
  7. /**
  8. * Installer extracts folders and files from a tar archive.
  9. *
  10. * @author Marcel Werk
  11. * @copyright 2001-2011 WoltLab GmbH
  12. * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  13. * @package com.woltlab.wcf
  14. * @subpackage system.setup
  15. * @category Community Framework
  16. */
  17. class Installer {
  18. protected $targetDir, $source, $folder, $fileHandler;
  19. /**
  20. * Creates a new Installer object.
  21. *
  22. * @param string $targetDir extract the files in this dir
  23. * @param string $source name of the source tar archive
  24. * @param FileHandler $fileHandler
  25. * @param string $folder extract only the files from this subfolder
  26. */
  27. public function __construct($targetDir, $source, $fileHandler = null, $folder = '') {
  28. $this->targetDir = FileUtil::addTrailingSlash($targetDir);
  29. $this->source = $source;
  30. $this->folder = $folder;
  31. $this->fileHandler = $fileHandler;
  32. $this->install();
  33. }
  34. /**
  35. * Creates the target directory if necessary.
  36. */
  37. protected function createTargetDir() {
  38. if (!@is_dir($this->targetDir)) {
  39. if (!FileUtil::makePath($this->targetDir, (FileUtil::isApacheModule() ? 0777 : 0755))) {
  40. throw new SystemException("Could not create dir '".$this->targetDir."'");
  41. }
  42. }
  43. if (FileUtil::isApacheModule() || !is_writeable($this->targetDir)) {
  44. $this->makeWriteable($this->targetDir);
  45. }
  46. }
  47. /**
  48. * Creates a directory in the target directory.
  49. *
  50. * @param string $dir
  51. */
  52. protected function createDir($dir) {
  53. if (!@is_dir($this->targetDir.$dir)) {
  54. $oldumask = umask(0);
  55. if (!@mkdir($this->targetDir.$dir, 0755, true)) {
  56. throw new SystemException("Could not create dir '".$this->targetDir.$dir."'");
  57. }
  58. umask($oldumask);
  59. }
  60. if (FileUtil::isApacheModule() || !is_writeable($this->targetDir.$dir)) {
  61. $this->makeWriteable($this->targetDir.$dir);
  62. }
  63. }
  64. /**
  65. * Touches a file in the target directory.
  66. *
  67. * @param string $file
  68. */
  69. public function touchFile($file) {
  70. @touch($this->targetDir.$file);
  71. $this->makeWriteable($this->targetDir.$file);
  72. }
  73. /**
  74. * Creates a file in the target directory.
  75. *
  76. * @param string $file
  77. * @param integer $index
  78. * @param Tar $tar
  79. */
  80. protected function createFile($file, $index, Tar $tar) {
  81. $tar->extract($index, $this->targetDir.$file);
  82. if (FileUtil::isApacheModule() || !is_writeable($this->targetDir.$file)) {
  83. $this->makeWriteable($this->targetDir.$file);
  84. }
  85. }
  86. /**
  87. * Starts the extracting of the files.
  88. */
  89. protected function install() {
  90. $this->createTargetDir();
  91. // open source archive
  92. $tar = new Tar($this->source);
  93. // distinct directories and files
  94. $directories = array();
  95. $files = array();
  96. foreach ($tar->getContentList() as $index => $file) {
  97. if (empty($this->folder) || StringUtil::indexOf($file['filename'], $this->folder) === 0) {
  98. if (!empty($this->folder)) {
  99. $file['filename'] = StringUtil::replace($this->folder, '', $file['filename']);
  100. }
  101. // remove leading slash
  102. $file['filename'] = FileUtil::removeLeadingSlash($file['filename']);
  103. if ($file['type'] == 'folder') {
  104. // remove trailing slash
  105. $directories[] = FileUtil::removeTrailingSlash($file['filename']);
  106. }
  107. else {
  108. $files[$index] = $file['filename'];
  109. }
  110. }
  111. }
  112. $this->checkFiles($files);
  113. // now create the directories
  114. $errors = array();
  115. foreach ($directories as $dir) {
  116. try {
  117. $this->createDir($dir);
  118. }
  119. catch (SystemException $e) {
  120. $errors[] = array('file' => $dir, 'code' => $e->getCode(), 'message' => $e->getMessage());
  121. }
  122. }
  123. // now untar all files
  124. foreach ($files as $index => $file) {
  125. try {
  126. $this->createFile($file, $index, $tar);
  127. }
  128. catch (SystemException $e) {
  129. $errors[] = array('file' => $file, 'code' => $e->getCode(), 'message' => $e->getMessage());
  130. }
  131. }
  132. if (count($errors) > 0) {
  133. throw new SystemException('error(s) during the installation of the files.', $errors);
  134. }
  135. $this->logFiles($files);
  136. // close tar
  137. $tar->close();
  138. }
  139. /**
  140. * Checkes whether the given files overwriting locked existing files.
  141. *
  142. * @param array $files list of files
  143. */
  144. protected function checkFiles(&$files) {
  145. if ($this->fileHandler != null && $this->fileHandler instanceof IFileHandler) {
  146. $this->fileHandler->checkFiles($files);
  147. }
  148. }
  149. /**
  150. * Logs the extracted files.
  151. *
  152. * @param array $files list of files
  153. */
  154. protected function logFiles(&$files) {
  155. if ($this->fileHandler != null && $this->fileHandler instanceof IFileHandler) {
  156. $this->fileHandler->logFiles($files);
  157. }
  158. }
  159. /**
  160. * Makes a file or directory writeable.
  161. *
  162. * @param string $target
  163. */
  164. protected function makeWriteable($target) {
  165. if (!preg_match('/^WIN/i', PHP_OS)) {
  166. if (!@chmod($target, 0777)) {
  167. //throw new SystemException("Could not chmod file '".$target."'");
  168. }
  169. }
  170. }
  171. }