cbffc1c2be74ede74529cb17a968658febf60b3b
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / FilePermissionUpdate.php
1 <?php
2 namespace TYPO3\CMS\Install\Updates;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Nicole Cordes <typo3@cordes.co>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Upgrade wizard which goes through all users and groups file permissions and stores them as list in a new field.
29 */
30 class FilePermissionUpdate extends AbstractUpdate {
31
32 /**
33 * @var \TYPO3\CMS\Install\Service\SqlSchemaMigrationService
34 */
35 protected $installToolSqlParser;
36
37 /**
38 * @var string
39 */
40 protected $title = 'Rewrite binary file permissions into detailed list';
41
42 /**
43 * Constructor function.
44 */
45 public function __construct() {
46 $this->installToolSqlParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService');
47 }
48
49 /**
50 * Checks if an update is needed
51 *
52 * @param string &$description The description for the update
53 * @return boolean TRUE if an update is needed, FALSE otherwise
54 */
55 public function checkForUpdate(&$description) {
56 $description = 'There are backend users and backend groups with specified file permissions.' .
57 ' This update migrates old combined (binary) file permissions to new separate ones.';
58 $updateNeeded = FALSE;
59 $updateStatements = $this->getUpdateStatements();
60 if (!empty($updateStatements['add'])) {
61 // Field might not be there, so we need an update run to add the field
62 return TRUE;
63 }
64 $beUsersFieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields('be_users');
65 if (isset($beUsersFieldInformation['fileoper_perms'])) {
66 // Fetch user records where the old permission field is not empty but the new one is
67 $notMigratedRowsCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
68 'uid',
69 'be_users',
70 $this->getWhereClause()
71 );
72 if ($notMigratedRowsCount > 0) {
73 $updateNeeded = TRUE;
74 }
75 } else {
76 $beGroupsFieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields('be_groups');
77 if (isset($beGroupsFieldInformation['fileoper_perms'])) {
78 // Fetch group records where the old permission field is not empty but the new one is
79 $notMigratedRowsCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
80 'uid',
81 'be_groups',
82 $this->getWhereClause()
83 );
84 if ($notMigratedRowsCount > 0) {
85 $updateNeeded = TRUE;
86 }
87 }
88 }
89 return $updateNeeded;
90 }
91
92 /**
93 * Performs the database update.
94 *
95 * @param array &$dbQueries Queries done in this update
96 * @param mixed &$customMessages Custom messages
97 * @return boolean TRUE on success, FALSE on error
98 */
99 public function performUpdate(array &$dbQueries, &$customMessages) {
100 // First perform all add update statements to database
101 $updateStatements = $this->getUpdateStatements();
102 foreach ((array) $updateStatements['add'] as $query) {
103 $GLOBALS['TYPO3_DB']->admin_query($query);
104 $dbQueries[] = $query;
105 if ($GLOBALS['TYPO3_DB']->sql_error()) {
106 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
107 return FALSE;
108 }
109 }
110
111 // Iterate over users and groups table to perform permission updates
112 $tablesToProcess = array('be_groups', 'be_users');
113 foreach ($tablesToProcess as $table) {
114 $records = $this->getRecordsFromTable($table);
115 foreach ($records as $singleRecord) {
116 $filePermission = $this->getFilePermissions($singleRecord['fileoper_perms']);
117 $updateArray = array(
118 'file_permissions' => $filePermission
119 );
120 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . (int)$singleRecord['uid'], $updateArray);
121 // Get last executed query
122 $dbQueries[] = str_replace(chr(10), ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
123 // Check for errors
124 if ($GLOBALS['TYPO3_DB']->sql_error()) {
125 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
126 return FALSE;
127 }
128 }
129 }
130
131 return TRUE;
132 }
133
134 /**
135 * Gets all create, add and change queries from core/ext_tables.sql
136 *
137 * @return array
138 */
139 protected function getUpdateStatements() {
140 $updateStatements = array();
141
142 // Get all necessary statements for ext_tables.sql file
143 $rawDefinitions = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('core') . '/ext_tables.sql');
144 $fieldDefinitionsFromFile = $this->installToolSqlParser->getFieldDefinitions_fileContent($rawDefinitions);
145 if (count($fieldDefinitionsFromFile)) {
146 $fieldDefinitionsFromCurrentDatabase = $this->installToolSqlParser->getFieldDefinitions_database();
147 $diff = $this->installToolSqlParser->getDatabaseExtra($fieldDefinitionsFromFile, $fieldDefinitionsFromCurrentDatabase);
148 $updateStatements = $this->installToolSqlParser->getUpdateSuggestions($diff);
149 }
150
151 return $updateStatements;
152 }
153
154 /**
155 * Processes the actual transformation from old binary file permissions to new separate list
156 *
157 * @param integer $oldFileOperationPermissions
158 * @return string
159 */
160 protected function getFilePermissions($oldFileOperationPermissions) {
161 if ($oldFileOperationPermissions == 0) {
162 return '';
163 }
164 $defaultOptions = array(
165 // File permissions
166 'addFile' => TRUE,
167 'readFile' => TRUE,
168 'writeFile' => TRUE,
169 'copyFile' => TRUE,
170 'moveFile' => TRUE,
171 'renameFile' => TRUE,
172 'unzipFile' => TRUE,
173 'deleteFile' => TRUE,
174 // Folder permissions
175 'addFolder' => TRUE,
176 'readFolder' => TRUE,
177 'writeFolder' => TRUE,
178 'copyFolder' => TRUE,
179 'moveFolder' => TRUE,
180 'renameFolder' => TRUE,
181 'deleteFolder' => TRUE,
182 'recursivedeleteFolder' => TRUE
183 );
184 if (!($oldFileOperationPermissions & 1)) {
185 unset($defaultOptions['addFile']);
186 unset($defaultOptions['readFile']);
187 unset($defaultOptions['writeFile']);
188 unset($defaultOptions['copyFile']);
189 unset($defaultOptions['moveFile']);
190 unset($defaultOptions['renameFile']);
191 unset($defaultOptions['deleteFile']);
192 }
193 if (!($oldFileOperationPermissions & 2)) {
194 unset($defaultOptions['unzipFile']);
195 }
196 if (!($oldFileOperationPermissions & 4)) {
197 unset($defaultOptions['addFolder']);
198 unset($defaultOptions['writeFolder']);
199 unset($defaultOptions['moveFolder']);
200 unset($defaultOptions['renameFolder']);
201 unset($defaultOptions['deleteFolder']);
202 }
203 if (!($oldFileOperationPermissions & 8)) {
204 unset($defaultOptions['copyFolder']);
205 }
206 if (!($oldFileOperationPermissions & 16)) {
207 unset($defaultOptions['recursivedeleteFolder']);
208 }
209
210 return implode(',', array_keys($defaultOptions));
211 }
212
213 /**
214 * Retrieve every record which needs to be processed
215 *
216 * @param string $table
217 * @return array
218 */
219 protected function getRecordsFromTable($table) {
220 $fields = implode(',', array('uid', 'fileoper_perms'));
221 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($fields, $table, $this->getWhereClause());
222 return $records;
223 }
224
225 /**
226 * Returns the where clause for database requests
227 *
228 * @return string
229 */
230 protected function getWhereClause() {
231 return 'fileoper_perms>0 AND ISNULL(file_permissions)';
232 }
233
234 }