FileController.php 8.11 KB
Newer Older
1
2
3
<?php
namespace TYPO3\CMS\Backend\Controller\File;

4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
8
9
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
10
 *
11
12
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
15
 * The TYPO3 project - inspiring people to share!
 */
Nicole Cordes's avatar
Nicole Cordes committed
16

17
use TYPO3\CMS\Core\Http\AjaxRequestHandler;
18
use TYPO3\CMS\Core\Resource\Folder;
Nicole Cordes's avatar
Nicole Cordes committed
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Backend\Utility\BackendUtility;
Nicole Cordes's avatar
Nicole Cordes committed
21

22
23
/**
 * Gateway for TCE (TYPO3 Core Engine) file-handling through POST forms.
24
 * This script serves as the file administration part of the TYPO3 Core Engine.
25
26
27
28
29
30
 * Basically it includes two libraries which are used to manipulate files on the server.
 * Before TYPO3 4.3, it was located in typo3/tce_file.php and redirected back to a
 * $redirectURL. Since 4.3 this class is also used for accessing via AJAX
 */
class FileController {

31
32
33
34
35
	/**
	 * Array of file-operations.
	 *
	 * @var array
	 */
36
37
	protected $file;

38
39
40
41
42
	/**
	 * Clipboard operations array
	 *
	 * @var array
	 */
43
44
	protected $CB;

45
46
47
48
49
	/**
	 * If existing files should be overridden.
	 *
	 * @var bool
	 */
50
51
	protected $overwriteExistingFiles;

52
53
54
55
56
57
	/**
	 * VeriCode - a hash of server specific value and other things which
	 * identifies if a submission is OK. (see $GLOBALS['BE_USER']->veriCode())
	 *
	 * @var string
	 */
58
59
	protected $vC;

60
61
62
63
64
	/**
	 * The page where the user should be redirected after everything is done
	 *
	 * @var string
	 */
65
66
	protected $redirect;

67
68
69
70
71
72
	/**
	 * Internal, dynamic:
	 * File processor object
	 *
	 * @var \TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
	 */
73
74
	protected $fileProcessor;

75
76
77
78
79
	/**
	 * The result array from the file processor
	 *
	 * @var array
	 */
80
81
	protected $fileData;

82
83
84
85
86
87
88
89
	/**
	 * Constructor
	 */
	public function __construct() {
		$GLOBALS['SOBE'] = $this;
		$this->init();
	}

90
91
92
93
94
	/**
	 * Registering incoming data
	 *
	 * @return void
	 */
95
	protected function init() {
96
		// Set the GPvars from outside
Nicole Cordes's avatar
Nicole Cordes committed
97
98
99
100
101
		$this->file = GeneralUtility::_GP('file');
		$this->CB = GeneralUtility::_GP('CB');
		$this->overwriteExistingFiles = GeneralUtility::_GP('overwriteExistingFiles');
		$this->vC = GeneralUtility::_GP('vC');
		$this->redirect = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('redirect'));
102
		$this->initClipboard();
103
		$this->fileProcessor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\File\ExtendedFileUtility::class);
104
105
106
107
108
109
110
111
112
	}

	/**
	 * Initialize the Clipboard. This will fetch the data about files to paste/delete if such an action has been sent.
	 *
	 * @return void
	 */
	public function initClipboard() {
		if (is_array($this->CB)) {
113
			$clipObj = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Clipboard\Clipboard::class);
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
			$clipObj->initializeClipboard();
			if ($this->CB['paste']) {
				$clipObj->setCurrentPad($this->CB['pad']);
				$this->file = $clipObj->makePasteCmdArray_file($this->CB['paste'], $this->file);
			}
			if ($this->CB['delete']) {
				$clipObj->setCurrentPad($this->CB['pad']);
				$this->file = $clipObj->makeDeleteCmdArray_file($this->file);
			}
		}
	}

	/**
	 * Performing the file admin action:
	 * Initializes the objects, setting permissions, sending data to object.
	 *
	 * @return void
	 */
	public function main() {
		// Initializing:
134
		$this->fileProcessor->init(array(), $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
135
		$this->fileProcessor->setActionPermissions();
136
137
		$this->fileProcessor->dontCheckForUnique = $this->overwriteExistingFiles ? 1 : 0;
		// Checking referrer / executing:
Nicole Cordes's avatar
Nicole Cordes committed
138
139
		$refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER'));
		$httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
140
		if ($httpHost !== $refInfo['host'] && $this->vC !== $this->getBackendUser()->veriCode() && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']) {
141
142
143
144
145
146
147
148
149
150
151
152
153
154
			$this->fileProcessor->writeLog(0, 2, 1, 'Referrer host "%s" and server host "%s" did not match!', array($refInfo['host'], $httpHost));
		} else {
			$this->fileProcessor->start($this->file);
			$this->fileData = $this->fileProcessor->processData();
		}
	}

	/**
	 * Redirecting the user after the processing has been done.
	 * Might also display error messages directly, if any.
	 *
	 * @return void
	 */
	public function finish() {
155
156
		// Push errors to flash message queue, if there are any
		$this->fileProcessor->pushErrorMessagesToFlashMessageQueue();
157
		BackendUtility::setUpdateSignal('updateFolderTree');
158
159
160
161
162
163
164
165
166
167
168
169
		if ($this->redirect) {
			\TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->redirect);
		}
	}

	/**
	 * Handles the actual process from within the ajaxExec function
	 * therefore, it does exactly the same as the real typo3/tce_file.php
	 * but without calling the "finish" method, thus makes it simpler to deal with the
	 * actual return value
	 *
	 * @param array $params Always empty.
170
	 * @param AjaxRequestHandler $ajaxObj The AjaxRequestHandler object used to return content and set content types
171
172
	 * @return void
	 */
173
	public function processAjaxRequest(array $params, AjaxRequestHandler $ajaxObj) {
174
175
176
		$this->init();
		$this->main();
		$errors = $this->fileProcessor->getErrorMessages();
177
		if (!empty($errors)) {
178
179
			$ajaxObj->setError(implode(',', $errors));
		} else {
180
181
182
183
184
185
186
187
188
			$flatResult = array();
			foreach ($this->fileData as $action => $results) {
				foreach ($results as $result) {
					if (is_array($result)) {
						foreach ($result as $subResult) {
							$flatResult[$action][] = $this->flattenResultDataValue($subResult);
						}
					} else {
						$flatResult[$action][] = $this->flattenResultDataValue($result);
189
190
191
					}
				}
			}
192
			$ajaxObj->addContent('result', $flatResult);
193
194
195
196
197
198
199
			if ($this->redirect) {
				$ajaxObj->addContent('redirect', $this->redirect);
			}
			$ajaxObj->setContentFormat('json');
		}
	}

200
201
202
203
204
205
206
207
208
209
210
211
212
	/**
	 * Ajax entry point to check if a file exists in a folder
	 *
	 * @param array $params Always empty.
	 * @param AjaxRequestHandler $ajaxObj The AjaxRequestHandler object used to return content and set content types
	 * @return void
	 */
	public function fileExistsAjaxRequest(array $params, AjaxRequestHandler $ajaxObj) {
		$fileName = GeneralUtility::_GP('fileName');
		$fileTarget = GeneralUtility::_GP('fileTarget');

		/** @var \TYPO3\CMS\Core\Resource\ResourceFactory $fileFactory */
		$fileFactory = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ResourceFactory::class);
213
		/** @var Folder $fileTargetObject */
214
215
216
		$fileTargetObject = $fileFactory->retrieveFileOrFolderObject($fileTarget);
		$processedFileName = $fileTargetObject->getStorage()->processUploadedFileName($fileTargetObject, $fileName);

217
218
219
220
221
		$result = FALSE;
		if ($fileTargetObject->hasFile($processedFileName)) {
			$result = $this->flattenResultDataValue($fileTargetObject->getStorage()->getFileInFolder($processedFileName, $fileTargetObject));
		}
		$ajaxObj->addContent('result', $result);
222
223
224
		$ajaxObj->setContentFormat('json');
	}

225
226
227
228
229
230
231
232
233
234
	/**
	 * Flatten result value from FileProcessor
	 *
	 * The value can be a File, Folder or boolean
	 *
	 * @param bool|\TYPO3\CMS\Core\Resource\File|\TYPO3\CMS\Core\Resource\Folder $result
	 * @return bool|string|array
	 */
	protected function flattenResultDataValue($result) {
		if ($result instanceof \TYPO3\CMS\Core\Resource\File) {
235
236
237
238
239
240
241
			$thumbUrl = '';
			if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $result->getExtension())) {
				$processedFile = $result->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, array());
				if ($processedFile) {
					$thumbUrl = $processedFile->getPublicUrl(TRUE);
				}
			}
242
243
244
245
246
			$result = array_merge(
				$result->toArray(),
				array (
					'date' => BackendUtility::date($result->getModificationTime()),
					'iconClasses' => \TYPO3\CMS\Backend\Utility\IconUtility::mapFileExtensionToSpriteIconClass($result->getExtension()),
247
					'thumbUrl' => $thumbUrl
248
249
250
251
252
253
254
255
				)
			);
		} elseif ($result instanceof \TYPO3\CMS\Core\Resource\Folder) {
			$result = $result->getIdentifier();
		}

		return $result;
	}
256

257
258
259
260
261
262
263
264
265
	/**
	 * Returns the current BE user.
	 *
	 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
	 */
	protected function getBackendUser() {
		return $GLOBALS['BE_USER'];
	}

266
}