[TASK] Apply quoteJSvalue or htmlspecialchars to getModuleUrl
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / Wizard / RteController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\Wizard;
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 TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Script Class for rendering the full screen RTE display
23 *
24 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
25 */
26 class RteController extends AbstractWizardController {
27
28 /**
29 * document template object
30 *
31 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
32 */
33 public $doc;
34
35 /**
36 * Content accumulation for the module.
37 *
38 * @var string
39 */
40 public $content;
41
42 /**
43 * Wizard parameters, coming from TCEforms linking to the wizard.
44 *
45 * @var array
46 */
47 public $P;
48
49 /**
50 * If set, launch a new window with the current records pid.
51 *
52 * @var string
53 */
54 public $popView;
55
56 /**
57 * Set to the URL of this script including variables which is needed to re-display the form. See main()
58 *
59 * @var string
60 */
61 public $R_URI;
62
63 /**
64 * Constructor
65 */
66 public function __construct() {
67 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_wizards.xlf');
68 $GLOBALS['SOBE'] = $this;
69
70 $this->init();
71 }
72
73 /**
74 * Initialization of the class
75 *
76 * @return void
77 */
78 protected function init() {
79 // Setting GPvars:
80 $this->P = GeneralUtility::_GP('P');
81 $this->popView = GeneralUtility::_GP('popView');
82 $this->R_URI = GeneralUtility::linkThisScript(array('popView' => ''));
83 // "Module name":
84 $this->MCONF['name'] = 'wizard_rte';
85 // Starting the document template object:
86 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
87 $this->doc->backPath = $this->getBackPath();
88 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/wizard_rte.html');
89 // Need to NOT have the page wrapped in DIV since if we do that we destroy
90 // the feature that the RTE spans the whole height of the page!!!
91 $this->doc->divClass = '';
92 $this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db')) . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
93 }
94
95 /**
96 * Main function, rendering the document with the iframe with the RTE in.
97 *
98 * @return void
99 */
100 public function main() {
101 // Translate id to the workspace version:
102 if ($versionRec = BackendUtility::getWorkspaceVersionOfRecord($this->getBackendUserAuthentication()->workspace, $this->P['table'], $this->P['uid'], 'uid')) {
103 $this->P['uid'] = $versionRec['uid'];
104 }
105 // If all parameters are available:
106 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
107 // Getting the raw record (we need only the pid-value from here...)
108 $rawRec = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
109 BackendUtility::fixVersioningPid($this->P['table'], $rawRec);
110
111 // override the default jumpToUrl
112 $this->doc->JScodeArray['jumpToUrl'] = '
113 function jumpToUrl(URL,formEl) {
114 if (document.editform) {
115 if (!TBE_EDITOR.isFormChanged()) {
116 window.location.href = URL;
117 } else if (formEl) {
118 if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
119 }
120 } else {
121 window.location.href = URL;
122 }
123 }
124 ';
125
126 // Setting JavaScript of the pid value for viewing:
127 if ($this->popView) {
128 $this->doc->JScode = $this->doc->wrapScriptTags(BackendUtility::viewOnClick($rawRec['pid'], '', BackendUtility::BEgetRootLine($rawRec['pid'])));
129 }
130 // Initialize TCeforms - for rendering the field:
131 $tceforms = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Form\FormEngine::class);
132 // Init...
133 $tceforms->initDefaultBEMode();
134 // SPECIAL: Disables all wizards - we are NOT going to need them.
135 $tceforms->disableWizards = 1;
136 // Initialize style for RTE object:
137 // Getting reference to the RTE object used to render the field!
138 $RTEobj = BackendUtility::RTEgetObj();
139 if ($RTEobj->ID == 'rte') {
140 $RTEobj->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border:solid 0px;';
141 }
142 // Fetching content of record:
143 $trData = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Form\DataPreprocessor::class);
144 $trData->lockRecords = 1;
145 $trData->fetchRecord($this->P['table'], $this->P['uid'], '');
146 // Getting the processed record content out:
147 $rec = reset($trData->regTableItems_data);
148 $rec['uid'] = $this->P['uid'];
149 $rec['pid'] = $rawRec['pid'];
150 // TSconfig, setting width:
151 $fieldTSConfig = $tceforms->setTSconfig($this->P['table'], $rec, $this->P['field']);
152 if ((string)$fieldTSConfig['RTEfullScreenWidth'] !== '') {
153 $width = $fieldTSConfig['RTEfullScreenWidth'];
154 } else {
155 $width = '100%';
156 }
157 // Get the form field and wrap it in the table with the buttons:
158 $formContent = $tceforms->getSoloField($this->P['table'], $rec, $this->P['field']);
159 $formContent = '
160
161
162 <!--
163 RTE wizard:
164 -->
165 <table border="0" cellpadding="0" cellspacing="0" width="' . $width . '" id="typo3-rtewizard">
166 <tr>
167 <td width="' . $width . '" colspan="2" id="c-formContent">' . $formContent . '</td>
168 <td></td>
169 </tr>
170 </table>';
171 // Adding hidden fields:
172 $formContent .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($this->R_URI) . '" />
173 <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction');
174 // Finally, add the whole setup:
175 $this->content .= $tceforms->printNeededJSFunctions_top() . $formContent . $tceforms->printNeededJSFunctions();
176 } else {
177 // ERROR:
178 $this->content .= $this->doc->section($this->getLanguageService()->getLL('forms_title'), '<span class="typo3-red">' . $this->getLanguageService()->getLL('table_noData', TRUE) . '</span>', 0, 1);
179 }
180 // Setting up the buttons and markers for docheader
181 $docHeaderButtons = $this->getButtons();
182 $markers['CONTENT'] = $this->content;
183 // Build the <body> for the module
184 $this->content = $this->doc->startPage('');
185 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
186 $this->content .= $this->doc->endPage();
187 $this->content = $this->doc->insertStylesAndJS($this->content);
188 }
189
190 /**
191 * Outputting the accumulated content to screen
192 *
193 * @return void
194 */
195 public function printContent() {
196 $this->content .= $this->doc->endPage();
197 $this->content = $this->doc->insertStylesAndJS($this->content);
198 echo $this->content;
199 }
200
201 /**
202 * Create the panel of buttons for submitting the form or otherwise perform operations.
203 *
204 * @return array All available buttons as an assoc. array
205 */
206 protected function getButtons() {
207 $buttons = array(
208 'close' => '',
209 'save' => '',
210 'save_view' => '',
211 'save_close' => '',
212 'shortcut' => '',
213 'undo' => ''
214 );
215 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
216 $closeUrl = GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']);
217 // Getting settings for the undo button:
218 $undoButton = 0;
219 $undoRes = $this->getDatabaseConnection()->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $this->getDatabaseConnection()->fullQuoteStr($this->P['table'], 'sys_history') . ' AND recuid=' . (int)$this->P['uid'], '', 'tstamp DESC', '1');
220 if ($undoButtonR = $this->getDatabaseConnection()->sql_fetch_assoc($undoRes)) {
221 $undoButton = 1;
222 }
223 // Close
224 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars('jumpToUrl(unescape(\'' . rawurlencode($closeUrl) . '\')); return false;') . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-close') . '</a>';
225 // Save
226 $buttons['save'] = IconUtility::getSpriteIcon('actions-document-save', array('html' => '<input type="image" name="_savedok" class="c-inputButton" src="clear.gif" onclick="TBE_EDITOR.checkAndDoSubmit(1); return false;" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" />'));
227 // Save & View
228 $buttons['save_view'] = IconUtility::getSpriteIcon('actions-document-save-view', array('html' => '<input type="image" class="c-inputButton" name="_savedokview" src="clear.gif" onclick="' . htmlspecialchars('document.editform.redirect.value+=\'&popView=1\'; TBE_EDITOR.checkAndDoSubmit(1); return false;') . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDocShow', TRUE) . '" />'));
229 // Save & Close
230 $buttons['save_close'] = IconUtility::getSpriteIcon('actions-document-save-close', array('html' => '<input type="image" class="c-inputButton" name="_saveandclosedok" src="clear.gif" onclick="' . htmlspecialchars('document.editform.redirect.value=\'' . $closeUrl . '\'; TBE_EDITOR.checkAndDoSubmit(1); return false;') . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', TRUE) . '" />'));
231 // Undo/Revert:
232 if ($undoButton) {
233 $aOnClick = 'window.location.href=' .
234 GeneralUtility::quoteJSvalue(
235 BackendUtility::getModuleUrl(
236 'record_history',
237 array(
238 'element' => $this->P['table'] . ':' . $this->P['uid'],
239 'revert' => 'field:' . $this->P['field'],
240 'sumUp' => -1,
241 'returnUrl' => $this->R_URI,
242 )
243 )
244 ) . '; return false;';
245 $buttons['undo'] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"' . ' title="' . htmlspecialchars(sprintf($this->getLanguageService()->getLL('undoLastChange'), BackendUtility::calcAge(($GLOBALS['EXEC_TIME'] - $undoButtonR['tstamp']), $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')))) . '">' . IconUtility::getSpriteIcon('actions-edit-undo') . '</a>';
246 }
247 // Shortcut
248 if ($this->getBackendUserAuthentication()->mayMakeShortcut()) {
249 $buttons['shortcut'] = $this->doc->makeShortcutIcon('P', '', $this->MCONF['name'], 1);
250 }
251 }
252 return $buttons;
253 }
254
255 }