[BUGFIX] Denied file extensions still shown in upload forms
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / File / CreateFolderController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\File;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Module\AbstractModule;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Core\Imaging\Icon;
22 use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
23 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
24 use TYPO3\CMS\Core\Resource\ResourceFactory;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Core\Utility\MathUtility;
27
28 /**
29 * Script Class for the create-new script; Displays a form for creating up to 10 folders or one new text file
30 */
31 class CreateFolderController extends AbstractModule
32 {
33 /**
34 * @var int
35 */
36 public $folderNumber = 10;
37
38 /**
39 * Name of the filemount
40 *
41 * @var string
42 */
43 public $title;
44
45 /**
46 * @var int
47 */
48 public $number;
49
50 /**
51 * Set with the target path inputted in &target
52 *
53 * @var string
54 */
55 public $target;
56
57 /**
58 * The folder object which is the target directory
59 *
60 * @var \TYPO3\CMS\Core\Resource\Folder $folderObject
61 */
62 protected $folderObject;
63
64 /**
65 * Return URL of list module.
66 *
67 * @var string
68 */
69 public $returnUrl;
70
71 /**
72 * @var array
73 */
74 protected $pathInfo;
75
76 /**
77 * Accumulating content
78 *
79 * @var string
80 */
81 public $content;
82
83 /**
84 * Constructor
85 */
86 public function __construct()
87 {
88 parent::__construct();
89 $GLOBALS['SOBE'] = $this;
90 $this->init();
91 }
92
93 /**
94 * @throws InsufficientFolderAccessPermissionsException
95 * @throws \RuntimeException
96 */
97 protected function init()
98 {
99 // Initialize GPvars:
100 $this->number = GeneralUtility::_GP('number');
101 $this->target = ($combinedIdentifier = GeneralUtility::_GP('target'));
102 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
103 // create the folder object
104 if ($combinedIdentifier) {
105 $this->folderObject = ResourceFactory::getInstance()
106 ->getFolderObjectFromCombinedIdentifier($combinedIdentifier);
107 }
108 // Cleaning and checking target directory
109 if (!$this->folderObject) {
110 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:paramError', true);
111 $message = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:targetNoDir', true);
112 throw new \RuntimeException($title . ': ' . $message, 1294586845);
113 }
114 if ($this->folderObject->getStorage()->getUid() === 0) {
115 throw new InsufficientFolderAccessPermissionsException(
116 'You are not allowed to access folders outside your storages',
117 1375889838
118 );
119 }
120
121 $pathInfo = [
122 'combined_identifier' => $this->folderObject->getCombinedIdentifier(),
123 ];
124 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pathInfo);
125 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
126 $this->moduleTemplate->addJavaScriptCode(
127 'CreateFolderInlineJavaScript',
128 'var path = "' . $this->target . '";
129 function reload(a) {
130 if (!changed || (changed && confirm(' .
131 GeneralUtility::quoteJSvalue($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:mess.redraw'))
132 . '))) {
133 var params = "&target="+encodeURIComponent(path)+"&number="+a+"&returnUrl='
134 . rawurlencode($this->returnUrl)
135 . '";
136 window.location.href = '
137 . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('file_newfolder')) . '+params;
138 }
139 }
140 function backToList() {
141 top.goToModule("file_FilelistList");
142 }
143 var changed = 0;'
144 );
145 }
146
147 /**
148 * Main function, rendering the main module content
149 *
150 * @return void
151 */
152 public function main()
153 {
154 $lang = $this->getLanguageService();
155 $pageContent = '<h1>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.pagetitle') . '</h1>';
156
157 if ($this->folderObject->checkActionPermission('add')) {
158 $code = '<form role="form" action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" method="post" name="editform">';
159 // Making the selector box for the number of concurrent folder-creations
160 $this->number = MathUtility::forceIntegerInRange($this->number, 1, 10);
161 $code .= '
162 <div class="form-group">
163 <div class="form-section">
164 <div class="form-group">
165 <label for="number-of-new-folders">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.number_of_folders') . '</label> ' . BackendUtility::cshItem('xMOD_csh_corebe', 'file_newfolder') . '
166 <div class="form-control-wrap">
167 <div class="input-group">
168 <select class="form-control form-control-adapt" name="number" id="number-of-new-folders" onchange="reload(this.options[this.selectedIndex].value);">';
169 for ($a = 1; $a <= $this->folderNumber; $a++) {
170 $code .= '<option value="' . $a . '"' . ($this->number == $a ? ' selected="selected"' : '') . '>' . $a . '</option>';
171 }
172 $code .= '
173 </select>
174 </div>
175 </div>
176 </div>
177 </div>
178 ';
179 // Making the number of new-folder boxes needed:
180 for ($a = 0; $a < $this->number; $a++) {
181 $code .= '
182 <div class="form-section">
183 <div class="form-group">
184 <label for="folder_new_' . $a . '">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.label_newfolder') . ' ' . ($a + 1) . ':</label>
185 <div class="form-control-wrap">
186 <input type="text" class="form-control" id="folder_new_' . $a . '" name="file[newfolder][' . $a . '][data]" onchange="changed=true;" />
187 <input type="hidden" name="file[newfolder][' . $a . '][target]" value="' . htmlspecialchars($this->target) . '" />
188 </div>
189 </div>
190 </div>';
191 }
192 // Making submit button for folder creation:
193 $code .= '
194 </div><div class="form-group">
195 <input class="btn btn-default" type="submit" value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.submit', true) . '" />
196 <input type="hidden" name="redirect" value="' . htmlspecialchars($this->returnUrl) . '" />
197 </div>
198 ';
199
200 // Switching form tags:
201 $pageContent .= '<h3>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.newfolders', true) . '</h3>';
202 $pageContent .= '<div>' . $code . '</form></div>';
203 }
204
205 if ($this->folderObject->getStorage()->checkUserActionPermission('add', 'File')) {
206 $pageContent .= '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('online_media')) . '" method="post" name="editform2">';
207 // Create a list of allowed file extensions with the readable format "youtube, vimeo" etc.
208 $fileExtList = array();
209 $onlineMediaFileExt = OnlineMediaHelperRegistry::getInstance()->getSupportedFileExtensions();
210 foreach ($onlineMediaFileExt as $fileExt) {
211 if (GeneralUtility::verifyFilenameAgainstDenyPattern('.' . $fileExt)) {
212 $fileExtList[] = '<span class="label label-success">' . strtoupper(htmlspecialchars($fileExt)) . '</span>';
213 }
214 }
215 // Add form fields for adding media files:
216 $code = '
217 <div class="form-group">
218 <div class="form-section">
219 <div class="form-group">
220 <label for="newMedia">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.label', true) . '</label> ' . BackendUtility::cshItem('xMOD_csh_corebe', 'file_newMedia') . '
221 <div class="form-control-wrap">
222 <input class="form-control" type="text" id="newMedia" name="file[newMedia][0][url]"
223 placeholder="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.placeholder', true) . '" />
224 <input type="hidden" name="file[newMedia][0][target]" value="' . htmlspecialchars($this->target) . '" />
225 </div>
226 <div class="help-block">
227 ' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.allowedProviders', true) . '<br>
228 ' . implode(' ', $fileExtList) . '
229 </div>
230 </div>
231 </div>
232 </div>
233 ';
234 // Submit button for creation of a new media:
235 $code .= '
236 <div class="form-group">
237 <input class="btn btn-default" type="submit" value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.submit', true) . '" />
238 <input type="hidden" name="redirect" value="' . htmlspecialchars($this->returnUrl) . '" />
239 </div>
240 ';
241 $pageContent .= '<h3>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media', true) . '</h3>';
242 $pageContent .= '<div>' . $code . '</div>';
243 $pageContent .= '</form>';
244
245 $pageContent .= '<form action="' . BackendUtility::getModuleUrl('tce_file') . '" method="post" name="editform3">';
246 // Create a list of allowed file extensions with the nice format "*.jpg, *.gif" etc.
247 $fileExtList = array();
248 $textFileExt = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], true);
249 foreach ($textFileExt as $fileExt) {
250 if (GeneralUtility::verifyFilenameAgainstDenyPattern('.' . $fileExt)) {
251 $fileExtList[] = '<span class="label label-success">' . strtoupper(htmlspecialchars($fileExt)) . '</span>';
252 }
253 }
254 // Add form fields for creation of a new, blank text file:
255 $code = '
256 <div class="form-group">
257 <div class="form-section">
258 <div class="form-group">
259 <label for="newfile">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.label_newfile', true) . '</label> ' . BackendUtility::cshItem('xMOD_csh_corebe', 'file_newfile') . '
260 <div class="form-control-wrap">
261 <input class="form-control" type="text" id="newfile" name="file[newfile][0][data]" onchange="changed=true;" />
262 <input type="hidden" name="file[newfile][0][target]" value="' . htmlspecialchars($this->target) . '" />
263 </div>
264 <div class="help-block">
265 ' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:cm.allowedFileExtensions', true) . '<br>
266 ' . implode(' ', $fileExtList) . '
267 </div>
268 </div>
269 </div>
270 </div>
271 ';
272 // Submit button for creation of a new file:
273 $code .= '
274 <div class="form-group">
275 <input class="btn btn-default" type="submit" value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.newfile_submit', true) . '" />
276 <input type="hidden" name="redirect" value="' . htmlspecialchars($this->returnUrl) . '" />
277 </div>
278 ';
279 $pageContent .= '<h3>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.newfile', true) . '</h3>';
280 $pageContent .= '<div>' . $code . '</div>';
281 $pageContent .= '</form>';
282 }
283
284 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
285 // Back
286 if ($this->returnUrl) {
287 $backButton = $buttonBar->makeLinkButton()
288 ->setHref(GeneralUtility::linkThisUrl($this->returnUrl))
289 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.goBack'))
290 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-back', Icon::SIZE_SMALL));
291 $buttonBar->addButton($backButton);
292 }
293
294 $this->content .= '<div>' . $pageContent . '</div>';
295 $this->moduleTemplate->setContent($this->content);
296 }
297
298 /**
299 * Processes the request, currently everything is handled and put together via "main()"
300 *
301 * @param ServerRequestInterface $request the current request
302 * @param ResponseInterface $response
303 * @return ResponseInterface the response with the content
304 */
305 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
306 {
307 $this->main();
308 $response->getBody()->write($this->moduleTemplate->renderContent());
309 return $response;
310 }
311
312 /**
313 * Returns LanguageService
314 *
315 * @return \TYPO3\CMS\Lang\LanguageService
316 */
317 protected function getLanguageService()
318 {
319 return $GLOBALS['LANG'];
320 }
321 }