c2cd88770a834d26628356b75e30a89f922f59ae
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / File / ExtendedFileUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility\File;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
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 2 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 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Core\Resource\File;
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32
33 /**
34 * Extending class to class t3lib_basicFileFunctions
35 *
36 * Revised for TYPO3 3.6 May/2004 by Kasper Skårhøj
37 *
38 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
39 */
40 /**
41 * Contains functions for performing file operations like copying, pasting, uploading, moving, deleting etc. through the TCE
42 * Extending class to class t3lib_basicFileFunctions.
43 *
44 * see basicFileFunctions
45 * see document "TYPO3 Core API" for syntax
46 *
47 * This class contains functions primarily used by tce_file.php (TYPO3 Core Engine for file manipulation)
48 * Functions include copying, moving, deleting, uploading and so on...
49 *
50 * Important internal variables:
51 *
52 * $filemounts (see basicFileFunctions)
53 * $f_ext (see basicFileFunctions)
54 * ... All fileoperations must be within the filemount-paths. Further the fileextension MUST validate TRUE with the f_ext array
55 *
56 * The unzip-function allows unzip only if the destination path has it's f_ext[]['allow'] set to '*'!!
57 * You are allowed to copy/move folders within the same 'space' (web/ftp).
58 * You are allowed to copy/move folders between spaces (web/ftp) IF the destination has it's f_ext[]['allow'] set to '*'!
59 *
60 * Advice:
61 * You should always exclude php-files from the webspace. This will keep people from uploading, copy/moving and renaming files to become executable php scripts.
62 * You should never mount a ftp_space 'below' the webspace so that it reaches into the webspace. This is because if somebody unzips a zip-file in the ftp-space so that it reaches out into the webspace this will be a violation of the safety
63 * For example this is a bad idea: you have an ftp-space that is '/www/' and a web-space that is '/www/htdocs/'
64 *
65 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
66 */
67 class ExtendedFileUtility extends \TYPO3\CMS\Core\Utility\File\BasicFileUtility {
68
69 // External static variables:
70 // Notice; some of these are overridden in the start() method with values from $GLOBALS['TYPO3_CONF_VARS']['BE']
71 // Path to unzip-program (with trailing '/')
72 /**
73 * @todo Define visibility
74 */
75 public $unzipPath = '';
76
77 // If set, the uploaded files will overwrite existing files.
78 /**
79 * @todo Define visibility
80 */
81 public $dontCheckForUnique = 0;
82
83 // This array is self-explaining (look in the class below).
84 // It grants access to the functions. This could be set from outside in order to enabled functions to users.
85 // See also the function init_actionPerms() which takes input directly from the user-record
86 /**
87 * @todo Define visibility
88 */
89 public $actionPerms = array(
90 'deleteFile' => 0,
91 // Deleting files physically
92 'deleteFolder' => 0,
93 // Deleting folders physically
94 'deleteFolderRecursively' => 0,
95 // normally folders are deleted by the PHP-function rmdir(), but with this option a user deletes with 'rm -Rf ....' which is pretty wild!
96 'moveFile' => 0,
97 'moveFolder' => 0,
98 'copyFile' => 0,
99 'copyFolder' => 0,
100 'newFolder' => 0,
101 'newFile' => 0,
102 'editFile' => 0,
103 'unzipFile' => 0,
104 'uploadFile' => 0,
105 'renameFile' => 0,
106 'renameFolder' => 0
107 );
108
109 // This is regarded to be the recycler folder
110 /**
111 * @todo Define visibility
112 */
113 public $recyclerFN = '_recycler_';
114
115 /**
116 * Whether to use recycler (0 = no, 1 = if available, 2 = always)
117 *
118 * @var integer
119 * @deprecated since TYPO3 6.0
120 * @todo Define visibility
121 */
122 public $useRecycler = 1;
123
124 // Internal, dynamic
125 // Will contain map between upload ID and the final filename
126 /**
127 * @todo Define visibility
128 */
129 public $internalUploadMap = array();
130
131 /**
132 * @todo Define visibility
133 */
134 public $lastError = '';
135
136 /**
137 * @var array
138 */
139 protected $fileCmdMap;
140
141 /**
142 * The File Factory
143 *
144 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
145 */
146 protected $fileFactory;
147
148
149 /**
150 * @var FileRepository
151 */
152 protected $fileRepository;
153
154 /**
155 * Initialization of the class
156 *
157 * @param array $fileCmds Array with the commands to execute. See "TYPO3 Core API" document
158 * @return void
159 * @todo Define visibility
160 */
161 public function start($fileCmds) {
162 $unzipPath = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path']);
163 if (substr($unzipPath, -1) !== '/' && is_dir($unzipPath)) {
164 // Make sure the path ends with a slash
165 $unzipPath .= '/';
166 }
167 $this->unzipPath = $unzipPath;
168 // Initialize Object Factory
169 $this->fileFactory = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
170 // Initialize Object Factory
171 $this->fileRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
172 // Initializing file processing commands:
173 $this->fileCmdMap = $fileCmds;
174 }
175
176 /**
177 * Sets up permission to perform file/directory operations.
178 * See below or the be_user-table for the significance of the various bits in $setup.
179 *
180 * @param integer $setup File permission integer from BE_USER OR'ed with permissions of back-end groups this user is a member of
181 * @return void
182 * @todo Define visibility
183 */
184 public function init_actionPerms($setup) {
185 // Files: Upload,Copy,Move,Delete,Rename
186 if (($setup & 1) == 1) {
187 $this->actionPerms['uploadFile'] = 1;
188 $this->actionPerms['copyFile'] = 1;
189 $this->actionPerms['moveFile'] = 1;
190 $this->actionPerms['deleteFile'] = 1;
191 $this->actionPerms['renameFile'] = 1;
192 $this->actionPerms['editFile'] = 1;
193 $this->actionPerms['newFile'] = 1;
194 }
195 // Files: Unzip
196 if (($setup & 2) == 2) {
197 $this->actionPerms['unzipFile'] = 1;
198 }
199 // Directory: Move,Delete,Rename,New
200 if (($setup & 4) == 4) {
201 $this->actionPerms['moveFolder'] = 1;
202 $this->actionPerms['deleteFolder'] = 1;
203 $this->actionPerms['renameFolder'] = 1;
204 $this->actionPerms['newFolder'] = 1;
205 }
206 // Directory: Copy
207 if (($setup & 8) == 8) {
208 $this->actionPerms['copyFolder'] = 1;
209 }
210 // Directory: Delete recursively (rm -Rf)
211 if (($setup & 16) == 16) {
212 $this->actionPerms['deleteFolderRecursively'] = 1;
213 }
214 }
215
216 /**
217 * Processing the command array in $this->fileCmdMap
218 *
219 * @return mixed FALSE, if the file functions were not initialized
220 * @throws \UnexpectedValueException
221 * @todo Define visibility
222 */
223 public function processData() {
224 $result = array();
225 if (!$this->isInit) {
226 return FALSE;
227 }
228 if (is_array($this->fileCmdMap)) {
229 // Check if there were uploads expected, but no one made
230 if ($this->fileCmdMap['upload']) {
231 $uploads = $this->fileCmdMap['upload'];
232 foreach ($uploads as $upload) {
233 if (!$_FILES[('upload_' . $upload['data'])]['name']) {
234 unset($this->fileCmdMap['upload'][$upload['data']]);
235 }
236 }
237 if (count($this->fileCmdMap['upload']) == 0) {
238 $this->writelog(1, 1, 108, 'No file was uploaded!', '');
239 }
240 }
241 // Traverse each set of actions
242 foreach ($this->fileCmdMap as $action => $actionData) {
243 // Traverse all action data. More than one file might be affected at the same time.
244 if (is_array($actionData)) {
245 $result[$action] = array();
246 foreach ($actionData as $cmdArr) {
247 // Clear file stats
248 clearstatcache();
249 // Branch out based on command:
250 switch ($action) {
251 case 'delete':
252 $result[$action][] = $this->func_delete($cmdArr);
253 break;
254 case 'copy':
255 $result[$action][] = $this->func_copy($cmdArr);
256 break;
257 case 'move':
258 $result[$action][] = $this->func_move($cmdArr);
259 break;
260 case 'rename':
261 $result[$action][] = $this->func_rename($cmdArr);
262 break;
263 case 'newfolder':
264 $result[$action][] = $this->func_newfolder($cmdArr);
265 break;
266 case 'newfile':
267 $result[$action][] = $this->func_newfile($cmdArr);
268 break;
269 case 'editfile':
270 $result[$action][] = $this->func_edit($cmdArr);
271 break;
272 case 'upload':
273 $result[$action][] = $this->func_upload($cmdArr);
274 break;
275 case 'unzip':
276 $result[$action][] = $this->func_unzip($cmdArr);
277 break;
278 }
279 // Hook for post-processing the action
280 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'])) {
281 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'] as $classRef) {
282 $hookObject = GeneralUtility::getUserObj($classRef);
283 if (!$hookObject instanceof \TYPO3\CMS\Core\Utility\File\ExtendedFileUtilityProcessDataHookInterface) {
284 throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Core\\Utility\\File\\ExtendedFileUtilityProcessDataHookInterface', 1279719168);
285 }
286 $hookObject->processData_postProcessAction($action, $cmdArr, $result[$action], $this);
287 }
288 }
289 }
290 }
291 }
292 }
293 return $result;
294 }
295
296 /**
297 * Adds log error messages from the operations of this script instance to the FlashMessageQueue
298 *
299 * @param string $redirect Redirect URL (for creating link in message)
300 * @return void
301 * @todo Define visibility
302 */
303 public function printLogErrorMessages($redirect = '') {
304 $this->getErrorMessages();
305 }
306
307 /**
308 * Adds log error messages from the previous file operations of this script instance
309 * to the FlashMessageQueue
310 *
311 * @return void
312 * @todo Define visibility
313 */
314 public function getErrorMessages() {
315 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_log', 'type = 2 AND userid = ' . intval($GLOBALS['BE_USER']->user['uid']) . ' AND tstamp=' . intval($GLOBALS['EXEC_TIME']) . ' AND error<>0');
316 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
317 $logData = unserialize($row['log_data']);
318 $msg = $row['error'] . ': ' . sprintf($row['details'], $logData[0], $logData[1], $logData[2], $logData[3], $logData[4]);
319 $flashMessage = GeneralUtility::makeInstance(
320 'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
321 $msg,
322 '',
323 \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR,
324 TRUE
325 );
326 $this->addFlashMessage($flashMessage);
327 }
328 $GLOBALS['TYPO3_DB']->sql_free_result($res);
329 }
330
331 /**
332 * Goes back in the path and checks in each directory if a folder named $this->recyclerFN (usually '_recycler_') is present.
333 * If a folder in the tree happens to be a _recycler_-folder (which means that we're deleting something inside a _recycler_-folder) this is ignored
334 *
335 * @param string $theFile Takes a valid Path ($theFile)
336 * @return string Returns the path (without trailing slash) of the closest recycle-folder if found. Else FALSE.
337 * @todo To be put in Storage with a better concept
338 * @todo Define visibility
339 * @deprecated since TYPO3 6.0, use \TYPO3\CMS\Core\Resource\ResourceStorage method instead
340 */
341 public function findRecycler($theFile) {
342 GeneralUtility::logDeprecatedFunction();
343 if ($this->isPathValid($theFile)) {
344 $theFile = $this->cleanDirectoryName($theFile);
345 $fI = GeneralUtility::split_fileref($theFile);
346 $c = 0;
347 // !!! Method has been put in the storage, can be saftely removed
348 $rDir = $fI['path'] . $this->recyclerFN;
349 while ($this->checkPathAgainstMounts($fI['path']) && $c < 20) {
350 if (@is_dir($rDir) && $this->recyclerFN != $fI['file']) {
351 return $rDir;
352 }
353 $theFile = $fI['path'];
354 $theFile = $this->cleanDirectoryName($theFile);
355 $fI = GeneralUtility::split_fileref($theFile);
356 $c++;
357 }
358 }
359 }
360
361 /**
362 * Logging file operations
363 *
364 * @param integer $action The action number. See the functions in the class for a hint. Eg. edit is '9', upload is '1' ...
365 * @param integer $error The severity: 0 = message, 1 = error, 2 = System Error, 3 = security notice (admin)
366 * @param integer $details_nr This number is unique for every combination of $type and $action. This is the error-message number, which can later be used to translate error messages.
367 * @param string $details This is the default, raw error message in english
368 * @param array $data Array with special information that may go into $details by "%s" marks / sprintf() when the log is shown
369 * @return void
370 * @see class.t3lib_beuserauth.php
371 * @todo Define visibility
372 */
373 public function writeLog($action, $error, $details_nr, $details, $data) {
374 // Type value for tce_file.php
375 $type = 2;
376 if (is_object($GLOBALS['BE_USER'])) {
377 $GLOBALS['BE_USER']->writelog($type, $action, $error, $details_nr, $details, $data);
378 }
379 $this->lastError = vsprintf($details, $data);
380 }
381
382 /*************************************
383 *
384 * File operation functions
385 *
386 **************************************/
387 /**
388 * Deleting files and folders (action=4)
389 *
390 * @param array $cmds $cmds['data'] is the file/folder to delete
391 * @return boolean Returns TRUE upon success
392 * @todo Define visibility
393 */
394 public function func_delete($cmds) {
395 $result = FALSE;
396 if (!$this->isInit) {
397 return $result;
398 }
399 // Example indentifier for $cmds['data'] => "4:mypath/tomyfolder/myfile.jpg"
400 // for backwards compatibility: the combined file identifier was the path+filename
401 $fileObject = $this->getFileObject($cmds['data']);
402 // @todo implement the recycler feature which has been removed from the original implementation
403 // checks to delete the file
404
405 if ($fileObject instanceof File) {
406 $refIndexRecords = $this->getDatabaseConnection()->exec_SELECTgetRows(
407 '*',
408 'sys_refindex',
409 'deleted=0 AND ref_table="sys_file" AND ref_uid=' . intval($fileObject->getUid())
410 );
411 // check if the file still has references
412 if (count($refIndexRecords) > 0) {
413 $shortcutContent = array();
414 foreach ($refIndexRecords as $fileReferenceRow) {
415 if ($fileReferenceRow['tablename'] === 'sys_file_reference') {
416 $row = $this->transformFileReferenceToRecordReference($fileReferenceRow);
417 $shortcutRecord = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord($row['tablename'], $row['recuid']);
418 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($row['tablename'], $shortcutRecord);
419 $onClick = 'showClickmenu("' . $row['tablename'] . '", "' . $row['recuid'] . '", "1", "+info,history,edit", "|", "");return false;';
420 $shortcutContent[] = '<a href="#" oncontextmenu="' . htmlspecialchars($onClick) . '" onclick="' . htmlspecialchars($onClick) . '">' . $icon . '</a>' . htmlspecialchars((\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($row['tablename'], $shortcutRecord) . ' [' . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordPath($shortcutRecord['pid'], '', 80) . ']'));
421 }
422 }
423
424 // render a message that the file could not be deleted
425 $flashMessage = GeneralUtility::makeInstance(
426 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
427 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.fileNotDeletedHasReferences'), $fileObject->getName()) . '<br />' . implode('<br />', $shortcutContent),
428 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.fileNotDeletedHasReferences'),
429 \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING, TRUE);
430 \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($flashMessage);
431 } else {
432 try {
433 $result = $fileObject->delete();
434
435 // show the user that the file was deleted
436 $flashMessage = GeneralUtility::makeInstance(
437 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
438 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.fileDeleted'), $fileObject->getName()),
439 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.fileDeleted'),
440 \TYPO3\CMS\Core\Messaging\FlashMessage::OK, TRUE);
441 \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($flashMessage);
442
443 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
444 $this->writelog(4, 1, 112, 'You are not allowed to access the file', array($fileObject->getIdentifier()));
445 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
446 $this->writelog(4, 1, 111, 'Target was not within your mountpoints! T="%s"', array($fileObject->getIdentifier()));
447 } catch (\RuntimeException $e) {
448 $this->writelog(4, 1, 110, 'Could not delete file "%s". Write-permission problem?', array($fileObject->getIdentifier()));
449 }
450 // Log success
451 $this->writelog(4, 0, 1, 'File "%s" deleted', array($fileObject->getIdentifier()));
452 }
453 } else {
454 try {
455 /** @var $fileObject \TYPO3\CMS\Core\Resource\FolderInterface */
456 if ($fileObject->getFileCount() > 0) {
457 // render a message that the folder could not be deleted because it still contains files
458 $flashMessage = GeneralUtility::makeInstance(
459 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
460 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.folderNotDeletedHasFiles'), $fileObject->getName()),
461 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.folderNotDeletedHasFiles'),
462 \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING, TRUE);
463 \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($flashMessage);
464
465 } else {
466 $result = $fileObject->delete(TRUE);
467
468 // notify the user that the folder was deleted
469 $flashMessage = GeneralUtility::makeInstance(
470 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
471 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.folderDeleted'), $fileObject->getName()),
472 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.folderDeleted'),
473 \TYPO3\CMS\Core\Messaging\FlashMessage::OK, TRUE);
474 \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($flashMessage);
475 }
476
477
478 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
479 $this->writelog(4, 1, 123, 'You are not allowed to access the directory', array($fileObject->getIdentifier()));
480 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
481 $this->writelog(4, 1, 121, 'Target was not within your mountpoints! T="%s"', array($fileObject->getIdentifier()));
482 } catch (\RuntimeException $e) {
483 $this->writelog(4, 1, 120, 'Could not delete directory! Write-permission problem? Is directory "%s" empty? (You are not allowed to delete directories recursively).', array($fileObject->getIdentifier()));
484 }
485 // Log success
486 $this->writelog(4, 0, 3, 'Directory "%s" deleted', array($fileObject->getIdentifier()));
487 }
488 return $result;
489 }
490
491 /**
492 * Maps results from the fal file reference table on the
493 * structure of the normal reference index table.
494 *
495 * @param array $referenceRecord
496 * @return array
497 */
498 protected function transformFileReferenceToRecordReference(array $referenceRecord) {
499 $fileReference = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'sys_file_reference', 'uid=' . (int)$referenceRecord['recuid']);
500 return array(
501 'recuid' => $fileReference['uid_foreign'],
502 'tablename' => $fileReference['tablenames'],
503 'field' => $fileReference['fieldname'],
504 'flexpointer' => '',
505 'softref_key' => '',
506 'sorting' => $fileReference['sorting_foreign']
507 );
508 }
509
510 /**
511 * Gets a File or a Folder object from an identifier [storage]:[fileId]
512 *
513 * @param string $identifier
514 * @return \TYPO3\CMS\Core\Resource\Folder|\TYPO3\CMS\Core\Resource\File
515 * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileException
516 */
517 protected function getFileObject($identifier) {
518 $object = $this->fileFactory->retrieveFileOrFolderObject($identifier);
519 if (!is_object($object)) {
520 throw new \TYPO3\CMS\Core\Resource\Exception\InvalidFileException('The item ' . $identifier . ' was not a file or directory!!', 1320122453);
521 }
522 return $object;
523 }
524
525 /**
526 * Copying files and folders (action=2)
527 *
528 * $cmds['data'] (string): The file/folder to copy
529 * + example "4:mypath/tomyfolder/myfile.jpg")
530 * + for backwards compatibility: the identifier was the path+filename
531 * $cmds['target'] (string): The path where to copy to.
532 * + example "2:targetpath/targetfolder/"
533 * $cmds['altName'] (string): Use an alternative name if the target already exists
534 *
535 * @param array $cmds Command details as described above
536 * @return \TYPO3\CMS\Core\Resource\File
537 */
538 protected function func_copy($cmds) {
539 if (!$this->isInit) {
540 return FALSE;
541 }
542 $sourceFileObject = $this->getFileObject($cmds['data']);
543 /** @var $targetFolderObject \TYPO3\CMS\Core\Resource\Folder */
544 $targetFolderObject = $this->getFileObject($cmds['target']);
545 // Basic check
546 if (!$targetFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
547 $this->writelog(2, 2, 100, 'Destination "%s" was not a directory', array($cmds['target']));
548 return FALSE;
549 }
550 // If this is TRUE, we append _XX to the file name if
551 $appendSuffixOnConflict = (string) $cmds['altName'];
552 $resultObject = NULL;
553 // Copying the file
554 if ($sourceFileObject instanceof File) {
555 try {
556 $conflictMode = $appendSuffixOnConflict !== '' ? 'renameNewFile' : 'cancel';
557 $resultObject = $sourceFileObject->copyTo($targetFolderObject, NULL, $conflictMode);
558 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
559 $this->writelog(2, 1, 114, 'You are not allowed to copy files', '');
560 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
561 $this->writelog(2, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
562 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
563 $this->writelog(2, 1, 111, 'Extension of file name "%s" is not allowed in "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
564 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
565 $this->writelog(2, 1, 112, 'File "%s" already exists in folder "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
566 } catch (\BadMethodCallException $e) {
567 $this->writelog(3, 1, 128, 'The function to copy a file between storages is not yet implemented', array());
568 } catch (\RuntimeException $e) {
569 $this->writelog(2, 2, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
570 }
571 if ($resultObject) {
572 $this->writelog(2, 0, 1, 'File "%s" copied to "%s"', array($sourceFileObject->getIdentifier(), $resultObject->getIdentifier()));
573 }
574 } else {
575 // Else means this is a Folder
576 $sourceFolderObject = $sourceFileObject;
577 try {
578 $conflictMode = $appendSuffixOnConflict !== '' ? 'renameNewFile' : 'cancel';
579 $resultObject = $sourceFolderObject->copyTo($targetFolderObject, NULL, $conflictMode);
580 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
581 $this->writelog(2, 1, 125, 'You are not allowed to copy directories', '');
582 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
583 $this->writelog(2, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
584 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException $e) {
585 $this->writelog(2, 1, 121, 'You don\'t have full access to the destination directory "%s"!', array($targetFolderObject->getIdentifier()));
586 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException $e) {
587 $this->writelog(2, 1, 122, 'Destination cannot be inside the target! D="%s", T="%s"', array($targetFolderObject->getIdentifier(), $sourceFolderObject->getIdentifier()));
588 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
589 $this->writelog(2, 1, 123, 'Target "%s" already exists!', array($targetFolderObject->getIdentifier()));
590 } catch (\BadMethodCallException $e) {
591 $this->writelog(3, 1, 129, 'The function to copy a folder between storages is not yet implemented', array());
592 } catch (\RuntimeException $e) {
593 $this->writelog(2, 2, 119, 'Directory "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
594 }
595 if ($resultObject) {
596 $this->writelog(2, 0, 2, 'Directory "%s" copied to "%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
597 }
598 }
599 return $resultObject;
600 }
601
602 /**
603 * Moving files and folders (action=3)
604 *
605 * $cmds['data'] (string): The file/folder to move
606 * + example "4:mypath/tomyfolder/myfile.jpg")
607 * + for backwards compatibility: the identifier was the path+filename
608 * $cmds['target'] (string): The path where to move to.
609 * + example "2:targetpath/targetfolder/"
610 * $cmds['altName'] (string): Use an alternative name if the target already exists
611 *
612 * @param array $cmds Command details as described above
613 * @return \TYPO3\CMS\Core\Resource\File
614 */
615 protected function func_move($cmds) {
616 if (!$this->isInit) {
617 return FALSE;
618 }
619 $sourceFileObject = $this->getFileObject($cmds['data']);
620 $targetFolderObject = $this->getFileObject($cmds['target']);
621 // Basic check
622 if (!$targetFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
623 $this->writelog(3, 2, 100, 'Destination "%s" was not a directory', array($cmds['target']));
624 return FALSE;
625 }
626 $alternativeName = (string) $cmds['altName'];
627 $resultObject = NULL;
628 // Moving the file
629 if ($sourceFileObject instanceof File) {
630 try {
631 if ($alternativeName !== '') {
632 // Don't allow overwriting existing files, but find a new name
633 $resultObject = $sourceFileObject->moveTo($targetFolderObject, $alternativeName, 'renameNewFile');
634 } else {
635 // Don't allow overwriting existing files
636 $resultObject = $sourceFileObject->moveTo($targetFolderObject, NULL, 'cancel');
637 }
638 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
639 $this->writelog(3, 1, 114, 'You are not allowed to move files', '');
640 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
641 $this->writelog(3, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
642 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
643 $this->writelog(3, 1, 111, 'Extension of file name "%s" is not allowed in "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
644 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
645 $this->writelog(3, 1, 112, 'File "%s" already exists in folder "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
646 } catch (\BadMethodCallException $e) {
647 $this->writelog(3, 1, 126, 'The function to move a file between storages is not yet implemented', array());
648 } catch (\RuntimeException $e) {
649 $this->writelog(3, 2, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
650 }
651 $this->writelog(3, 0, 1, 'File "%s" moved to "%s"', array($sourceFileObject->getIdentifier(), $resultObject->getIdentifier()));
652 } else {
653 // Else means this is a Folder
654 $sourceFolderObject = $sourceFileObject;
655 try {
656 if ($alternativeName !== '') {
657 // Don't allow overwriting existing files, but find a new name
658 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, $alternativeName, 'renameNewFile');
659 } else {
660 // Don't allow overwriting existing files
661 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, NULL, 'renameNewFile');
662 }
663 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
664 $this->writelog(3, 1, 125, 'You are not allowed to move directories', '');
665 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
666 $this->writelog(3, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
667 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException $e) {
668 $this->writelog(3, 1, 121, 'You don\'t have full access to the destination directory "%s"!', array($targetFolderObject->getIdentifier()));
669 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException $e) {
670 $this->writelog(3, 1, 122, 'Destination cannot be inside the target! D="%s", T="%s"', array($targetFolderObject->getIdentifier(), $sourceFolderObject->getIdentifier()));
671 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
672 $this->writelog(3, 1, 123, 'Target "%s" already exists!', array($targetFolderObject->getIdentifier()));
673 } catch (\BadMethodCallException $e) {
674 $this->writelog(3, 1, 127, 'The function to move a folder between storages is not yet implemented', array());
675 } catch (\RuntimeException $e) {
676 $this->writelog(3, 2, 119, 'Directory "%s" WAS NOT moved to "%s"! Write-permission problem?', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
677 }
678 $this->writelog(3, 0, 2, 'Directory "%s" moved to "%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
679 }
680 return $resultObject;
681 }
682
683 /**
684 * Renaming files or foldes (action=5)
685 *
686 * $cmds['data'] (string): The file/folder to copy
687 * + example "4:mypath/tomyfolder/myfile.jpg")
688 * + for backwards compatibility: the identifier was the path+filename
689 * $cmds['target'] (string): New name of the file/folder
690 *
691 * @param array $cmds Command details as described above
692 * @return \TYPO3\CMS\Core\Resource\File Returns the new file upon success
693 * @todo Define visibility
694 */
695 public function func_rename($cmds) {
696 if (!$this->isInit) {
697 return FALSE;
698 }
699 $sourceFileObject = $this->getFileObject($cmds['data']);
700 $targetFile = $cmds['target'];
701 $resultObject = NULL;
702 if ($sourceFileObject instanceof File) {
703 try {
704 // Try to rename the File
705 $resultObject = $sourceFileObject->rename($targetFile);
706 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
707 $this->writelog(5, 1, 102, 'You are not allowed to rename files!', '');
708 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
709 $this->writelog(5, 1, 101, 'Extension of file name "%s" was not allowed!', array($targetFile));
710 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
711 $this->writelog(5, 1, 120, 'Destination "%s" existed already!', array($targetFile));
712 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
713 $this->writelog(5, 1, 121, 'Destination path "%s" was not within your mountpoints!', array($targetFile));
714 } catch (\RuntimeException $e) {
715 $this->writelog(5, 1, 100, 'File "%s" was not renamed! Write-permission problem in "%s"?', array($sourceFileObject->getName(), $targetFile));
716 }
717 $this->writelog(5, 0, 1, 'File renamed from "%s" to "%s"', array($sourceFileObject->getName(), $targetFile));
718 } else {
719 // Else means this is a Folder
720 try {
721 // Try to rename the Folder
722 $resultObject = $sourceFileObject->rename($targetFile);
723 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
724 $this->writelog(5, 1, 111, 'You are not allowed to rename directories!', '');
725 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
726 $this->writelog(5, 1, 120, 'Destination "%s" existed already!', array($targetFile));
727 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
728 $this->writelog(5, 1, 121, 'Destination path "%s" was not within your mountpoints!', array($targetFile));
729 } catch (\RuntimeException $e) {
730 $this->writelog(5, 1, 110, 'Directory "%s" was not renamed! Write-permission problem in "%s"?', array($sourceFileObject->getName(), $targetFile));
731 }
732 $this->writelog(5, 0, 2, 'Directory renamed from "%s" to "%s"', array($sourceFileObject->getName(), $targetFile));
733 }
734 return $resultObject;
735 }
736
737 /**
738 * This creates a new folder. (action=6)
739 *
740 * $cmds['data'] (string): The new folder name
741 * $cmds['target'] (string): The path where to copy to.
742 * + example "2:targetpath/targetfolder/"
743 *
744 * @param array $cmds Command details as described above
745 * @return \TYPO3\CMS\Core\Resource\Folder Returns the new foldername upon success
746 * @todo Define visibility
747 */
748 public function func_newfolder($cmds) {
749 if (!$this->isInit) {
750 return FALSE;
751 }
752 $targetFolderObject = $this->getFileObject($cmds['target']);
753 if (!$targetFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
754 $this->writelog(6, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
755 return FALSE;
756 }
757 $resultObject = NULL;
758 try {
759 $folderName = $cmds['data'];
760 $resultObject = $targetFolderObject->createFolder($folderName);
761 $this->writelog(6, 0, 1, 'Directory "%s" created in "%s"', array($folderName, $targetFolderObject->getIdentifier() . '/'));
762 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
763 $this->writelog(6, 1, 103, 'You are not allowed to create directories!', '');
764 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
765 $this->writelog(6, 1, 102, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier() . '/'));
766 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
767 $this->writelog(6, 1, 101, 'File or directory "%s" existed already!', array($folderName));
768 } catch (\RuntimeException $e) {
769 $this->writelog(6, 1, 100, 'Directory "%s" not created. Write-permission problem in "%s"?', array($folderName, $targetFolderObject->getIdentifier() . '/'));
770 }
771 return $resultObject;
772 }
773
774 /**
775 * This creates a new file. (action=8)
776 * $cmds['data'] (string): The new file name
777 * $cmds['target'] (string): The path where to create it.
778 * + example "2:targetpath/targetfolder/"
779 *
780 * @param array $cmds Command details as described above
781 * @return string Returns the new filename upon success
782 * @todo Define visibility
783 */
784 public function func_newfile($cmds) {
785 if (!$this->isInit) {
786 return FALSE;
787 }
788 $targetFolderObject = $this->getFileObject($cmds['target']);
789 if (!$targetFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
790 $this->writelog(8, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
791 return FALSE;
792 }
793 $resultObject = NULL;
794 try {
795 $fileName = $cmds['data'];
796 $resultObject = $targetFolderObject->createFile($fileName);
797 $this->writelog(8, 0, 1, 'File created: "%s"', array($fileName));
798 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
799 $this->writelog(8, 1, 103, 'You are not allowed to create files!', '');
800 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
801 $this->writelog(8, 1, 102, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier()));
802 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
803 $this->writelog(8, 1, 101, 'File existed already in "%s"!', array($targetFolderObject->getIdentifier()));
804 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException $e) {
805 $this->writelog(8, 1, 106, 'File name "%s" was not allowed!', $fileName);
806 } catch (\RuntimeException $e) {
807 $this->writelog(8, 1, 100, 'File "%s" was not created! Write-permission problem in "%s"?', array($fileName, $targetFolderObject->getIdentifier()));
808 }
809 return $resultObject;
810 }
811
812 /**
813 * Editing textfiles or folders (action=9)
814 *
815 * @param array $cmds $cmds['data'] is the new content. $cmds['target'] is the target (file or dir)
816 * @return boolean Returns TRUE on success
817 * @todo Define visibility
818 */
819 public function func_edit($cmds) {
820 if (!$this->isInit) {
821 return FALSE;
822 }
823 // Example indentifier for $cmds['target'] => "4:mypath/tomyfolder/myfile.jpg"
824 // for backwards compatibility: the combined file identifier was the path+filename
825 $fileIdentifier = $cmds['target'];
826 $fileObject = $this->getFileObject($fileIdentifier);
827 // Example indentifier for $cmds['target'] => "2:targetpath/targetfolder/"
828 $content = $cmds['data'];
829 if (!$fileObject instanceof File) {
830 $this->writelog(9, 2, 123, 'Target "%s" was not a file!', array($fileIdentifier));
831 return FALSE;
832 }
833 $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'];
834 if (!GeneralUtility::inList($extList, $fileObject->getExtension())) {
835 $this->writelog(9, 1, 102, 'File extension "%s" is not a textfile format! (%s)', array($fileObject->getExtension(), $extList));
836 return FALSE;
837 }
838 try {
839 $fileObject->setContents($content);
840 clearstatcache();
841 $this->writelog(9, 0, 1, 'File saved to "%s", bytes: %s, MD5: %s ', array($fileObject->getIdentifier(), $fileObject->getSize(), md5($content)));
842 return TRUE;
843 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
844 $this->writelog(9, 1, 104, 'You are not allowed to edit files!', '');
845 return FALSE;
846 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileWritePermissionsException $e) {
847 $this->writelog(9, 1, 100, 'File "%s" was not saved! Write-permission problem?', array($fileObject->getIdentifier()));
848 return FALSE;
849 }
850 }
851
852 /**
853 * Upload of files (action=1)
854 * when having multiple uploads (HTML5-style), the array $_FILES looks like this:
855 * Array(
856 * [upload_1] => Array(
857 * [name] => Array(
858 * [0] => GData - Content-Elements and Media-Gallery.pdf
859 * [1] => CMS Expo 2011.txt
860 * )
861 * [type] => Array(
862 * [0] => application/pdf
863 * [1] => text/plain
864 * )
865 * [tmp_name] => Array(
866 * [0] => /Applications/MAMP/tmp/php/phpNrOB43
867 * [1] => /Applications/MAMP/tmp/php/phpD2HQAK
868 * )
869 * [size] => Array(
870 * [0] => 373079
871 * [1] => 1291
872 * )
873 * )
874 * )
875 * in HTML you'd need sth like this: <input type="file" name="upload_1[]" multiple="true" />
876 *
877 * @param array $cmds $cmds['data'] is the ID-number (points to the global var that holds the filename-ref ($_FILES['upload_' . $id]['name']) . $cmds['target'] is the target directory, $cmds['charset'] is the the character set of the file name (utf-8 is needed for JS-interaction)
878 * @return string Returns the new filename upon success
879 * @todo Define visibility
880 */
881 public function func_upload($cmds) {
882 if (!$this->isInit) {
883 return FALSE;
884 }
885 $uploadPosition = $cmds['data'];
886 $uploadedFileData = $_FILES['upload_' . $uploadPosition];
887 if (empty($uploadedFileData['name']) || is_array($uploadedFileData['name']) && empty($uploadedFileData['name'][0])) {
888 $this->writelog(1, 2, 108, 'No file was uploaded!', '');
889 return FALSE;
890 }
891 // Example indentifier for $cmds['target'] => "2:targetpath/targetfolder/"
892 $targetFolderObject = $this->getFileObject($cmds['target']);
893 // Uploading with non HTML-5-style, thus, make an array out of it, so we can loop over it
894 if (!is_array($uploadedFileData['name'])) {
895 $uploadedFileData = array(
896 'name' => array($uploadedFileData['name']),
897 'type' => array($uploadedFileData['type']),
898 'tmp_name' => array($uploadedFileData['tmp_name']),
899 'size' => array($uploadedFileData['size'])
900 );
901 }
902 $resultObjects = array();
903 $numberOfUploadedFilesForPosition = count($uploadedFileData['name']);
904 // Loop through all uploaded files
905 for ($i = 0; $i < $numberOfUploadedFilesForPosition; $i++) {
906 $fileInfo = array(
907 'name' => $uploadedFileData['name'][$i],
908 'type' => $uploadedFileData['type'][$i],
909 'tmp_name' => $uploadedFileData['tmp_name'][$i],
910 'size' => $uploadedFileData['size'][$i]
911 );
912 try {
913 // @todo can be improved towards conflict mode naming
914 if ($this->dontCheckForUnique) {
915 $conflictMode = 'replace';
916 } else {
917 $conflictMode = 'cancel';
918 }
919 /** @var $fileObject File */
920 $fileObject = $targetFolderObject->addUploadedFile($fileInfo, $conflictMode);
921 $this->fileRepository->addToIndex($fileObject);
922 $resultObjects[] = $fileObject;
923 $this->writelog(1, 0, 1, 'Uploading file "%s" to "%s"', array($fileInfo['name'], $targetFolderObject->getIdentifier()));
924 } catch (\TYPO3\CMS\Core\Resource\Exception\UploadException $e) {
925 $this->writelog(1, 2, 106, 'The upload has failed, no uploaded file found!', '');
926 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
927 $this->writelog(1, 1, 105, 'You are not allowed to upload files!', '');
928 } catch (\TYPO3\CMS\Core\Resource\Exception\UploadSizeException $e) {
929 $this->writelog(1, 1, 104, 'The uploaded file "%s" exceeds the size-limit', array($fileInfo['name']));
930 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
931 $this->writelog(1, 1, 103, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier()));
932 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
933 $this->writelog(1, 1, 102, 'Extension of file name "%s" is not allowed in "%s"!', array($fileInfo['name'], $targetFolderObject->getIdentifier()));
934 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
935 $this->writelog(1, 1, 101, 'No unique filename available in "%s"!', array($targetFolderObject->getIdentifier()));
936 } catch (\RuntimeException $e) {
937 $this->writelog(1, 1, 100, 'Uploaded file could not be moved! Write-permission problem in "%s"?', array($targetFolderObject->getIdentifier()));
938 }
939 }
940
941 return $resultObjects;
942 }
943
944 /**
945 * Unzipping file (action=7)
946 * This is permitted only if the user has fullAccess or if the file resides
947 *
948 * @param array $cmds $cmds['data'] is the zip-file. $cmds['target'] is the target directory. If not set we'll default to the same directory as the file is in.
949 * @return boolean Returns TRUE on success
950 * @todo Define visibility
951 */
952 public function func_unzip($cmds) {
953 if (!$this->isInit || $this->dont_use_exec_commands) {
954 return FALSE;
955 }
956 $theFile = $cmds['data'];
957 if (!@is_file($theFile)) {
958 $this->writelog(7, 2, 105, 'The file "%s" did not exist!', array($theFile));
959 return FALSE;
960 }
961 $fI = GeneralUtility::split_fileref($theFile);
962 if (!isset($cmds['target'])) {
963 $cmds['target'] = $fI['path'];
964 }
965 // Clean up destination directory
966 // !!! Method has been put in the local driver, can be saftely removed
967 $theDest = $this->is_directory($cmds['target']);
968 if (!$theDest) {
969 $this->writelog(7, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
970 return FALSE;
971 }
972 if (!$this->actionPerms['unzipFile']) {
973 $this->writelog(7, 1, 103, 'You are not allowed to unzip files', '');
974 return FALSE;
975 }
976 if ($fI['fileext'] != 'zip') {
977 $this->writelog(7, 1, 102, 'File extension is not "zip"', '');
978 return FALSE;
979 }
980 if (!$this->checkIfFullAccess($theDest)) {
981 $this->writelog(7, 1, 101, 'You don\'t have full access to the destination directory "%s"!', array($theDest));
982 return FALSE;
983 }
984 // !!! Method has been put in the sotrage driver, can be saftely removed
985 if ($this->checkPathAgainstMounts($theFile) && $this->checkPathAgainstMounts($theDest . '/')) {
986 // No way to do this under windows.
987 $cmd = $this->unzipPath . 'unzip -qq ' . escapeshellarg($theFile) . ' -d ' . escapeshellarg($theDest);
988 \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd);
989 $this->writelog(7, 0, 1, 'Unzipping file "%s" in "%s"', array($theFile, $theDest));
990 return TRUE;
991 } else {
992 $this->writelog(7, 1, 100, 'File "%s" or destination "%s" was not within your mountpoints!', array($theFile, $theDest));
993 return FALSE;
994 }
995 }
996
997 /**
998 * Get database connection
999 *
1000 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
1001 */
1002 protected function getDatabaseConnection() {
1003 return $GLOBALS['TYPO3_DB'];
1004 }
1005
1006 /**
1007 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
1008 */
1009 protected function getBackendUser() {
1010 return $GLOBALS['BE_USER'];
1011 }
1012
1013 }
1014
1015 ?>