Fixed bug #11003: htmlArea RTE: empty mutuallyExclusiveClasses array may cause js...
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / class.tx_rtehtmlarea_base.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com)
6 * (c) 2004-2009 Philipp Borgmann <philipp.borgmann@gmx.de>
7 * (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
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 * A RTE using the htmlArea editor
31 *
32 * @author Philipp Borgmann <philipp.borgmann@gmx.de>
33 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
34 *
35 * $Id$ *
36 */
37
38 require_once(PATH_t3lib.'class.t3lib_rteapi.php');
39 require_once(PATH_t3lib.'class.t3lib_cs.php');
40
41 class tx_rtehtmlarea_base extends t3lib_rteapi {
42
43 // Configuration of supported browsers
44 var $conf_supported_browser = array (
45 'msie' => array (
46 1 => array (
47 'version' => 5.5,
48 'system' => 'win'
49 )
50 ),
51 'gecko' => array (
52 1 => array (
53 'version' => 1.3
54 )
55 ),
56 'safari' => array (
57 1 => array (
58 'version' => 523
59 )
60 ),
61 'opera' => array (
62 1 => array (
63 'version' => 9.62
64 )
65 )
66 );
67
68 // Always hide these toolbar buttons (TYPO3 button name)
69 var $conf_toolbar_hide = array (
70 'showhelp', // Has no content yet
71 );
72
73 // The order of the toolbar: the name is the TYPO3-button name
74 var $defaultToolbarOrder;
75
76 // Conversion array: TYPO3 button names to htmlArea button names
77 var $convertToolbarForHtmlAreaArray = array (
78 'line' => 'InsertHorizontalRule',
79 'showhelp' => 'ShowHelp',
80 'textindicator' => 'TextIndicator',
81 'space' => 'space',
82 'bar' => 'separator',
83 'linebreak' => 'linebreak',
84 );
85
86 var $pluginButton = array();
87 var $pluginLabel = array();
88
89 // External:
90 var $RTEdivStyle; // Alternative style for RTE <div> tag.
91 public $httpTypo3Path;
92 var $extHttpPath; // full Path to this extension for http (so no Server path). It ends with "/"
93 var $siteURL; // TYPO3 site url
94 var $hostURL; // TYPO3 host url
95 var $typoVersion; // Typo3 version
96
97 // Internal, static:
98 var $ID = 'rtehtmlarea'; // Identifies the RTE as being the one from the "rte" extension if any external code needs to know...
99 var $debugMode = FALSE; // If set, the content goes into a regular TEXT area field - for developing testing of transformations. (Also any browser will load the field!)
100
101 // For the editor
102 var $client;
103
104 /**
105 * Reference to parent object, which is an instance of the TCEforms
106 *
107 * @var t3lib_TCEforms
108 */
109 var $TCEform;
110 var $elementId;
111 var $elementParts;
112 var $tscPID;
113 var $typeVal;
114 var $thePid;
115 var $RTEsetup;
116 var $thisConfig;
117 var $confValues;
118 public $language;
119 public $contentTypo3Language;
120 public $contentISOLanguage;
121 public $contentCharset;
122 public $OutputCharset;
123 var $editorCSS;
124 var $specConf;
125 var $toolbar = array(); // Save the buttons for the toolbar
126 var $toolbar_level_size; // The size for each level in the toolbar:
127 var $toolbarOrderArray = array();
128 protected $pluginEnabledArray = array(); // Array of plugin id's enabled in the current RTE editing area
129 protected $pluginEnabledCumulativeArray = array(); // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form
130 public $registeredPlugins = array(); // Array of registered plugins indexed by their plugin Id's
131
132 /**
133 * Returns true if the RTE is available. Here you check if the browser requirements are met.
134 * If there are reasons why the RTE cannot be displayed you simply enter them as text in ->errorLog
135 *
136 * @return boolean TRUE if this RTE object offers an RTE in the current browser environment
137 */
138
139 function isAvailable() {
140 global $TYPO3_CONF_VARS;
141
142 $this->client = $this->clientInfo();
143 $this->errorLog = array();
144 if (!$this->debugMode) { // If debug-mode, let any browser through
145 $rteIsAvailable = 0;
146 $rteConfBrowser = $this->conf_supported_browser;
147 if (is_array($rteConfBrowser)) {
148 foreach ($rteConfBrowser as $browser => $browserConf) {
149 if ($browser == $this->client['BROWSER']) {
150 // Config for Browser found, check it:
151 if (is_array($browserConf)) {
152 foreach ($browserConf as $browserConfNr => $browserConfSub) {
153 if ($browserConfSub['version'] <= $this->client['VERSION'] || empty($browserConfSub['version'])) {
154 // Version is correct
155 if ($browserConfSub['system'] == $this->client['SYSTEM'] || empty($browserConfSub['system'])) {
156 // System is correctly
157 $rteIsAvailable = 1;
158 }// End of System
159 }// End of Version
160 }// End of foreach-BrowserSubpart
161 } else {
162 // no config for this browser found, so all versions or system with this browsers are allow
163 $rteIsAvailable = 1;
164 }
165 } // End of Browser Check
166 } // foreach: Browser Check
167 } else {
168 // no Browser config for this RTE-Editor, so all Clients are allow
169 }
170 if (!$rteIsAvailable) {
171 $this->errorLog[] = 'rte: Browser not supported. Only msie Version 5 or higher and Mozilla based client 1. and higher.';
172 }
173 if (t3lib_div::int_from_ver(TYPO3_version) < 4000000) {
174 $rteIsAvailable = 0;
175 $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
176 }
177 }
178 if ($rteIsAvailable) return true;
179 }
180
181 /**
182 * Draws the RTE as an iframe
183 *
184 * @param object Reference to parent object, which is an instance of the TCEforms.
185 * @param string The table name
186 * @param string The field name
187 * @param array The current row from which field is being rendered
188 * @param array Array of standard content for rendering form fields from TCEforms. See TCEforms for details on this. Includes for instance the value and the form field name, java script actions and more.
189 * @param array "special" configuration - what is found at position 4 in the types configuration of a field from record, parsed into an array.
190 * @param array Configuration for RTEs; A mix between TSconfig and otherwise. Contains configuration for display, which buttons are enabled, additional transformation information etc.
191 * @param string Record "type" field value.
192 * @param string Relative path for images/links in RTE; this is used when the RTE edits content from static files where the path of such media has to be transformed forth and back!
193 * @param integer PID value of record (true parent page id)
194 * @return string HTML code for RTE!
195 */
196
197 function drawRTE($parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
198 global $BE_USER, $LANG, $TYPO3_DB, $TYPO3_CONF_VARS;
199
200 $this->TCEform =& $parentObject;
201 $inline =& $this->TCEform->inline;
202 $LANG->includeLLFile('EXT:' . $this->ID . '/locallang.xml');
203 $this->client = $this->clientInfo();
204 $this->typoVersion = t3lib_div::int_from_ver(TYPO3_version);
205 $this->userUid = 'BE_' . $BE_USER->user['uid'];
206
207 // Draw form element:
208 if ($this->debugMode) { // Draws regular text area (debug mode)
209 $item = parent::drawRTE($this->TCEform, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
210 } else { // Draw real RTE
211
212 /* =======================================
213 * INIT THE EDITOR-SETTINGS
214 * =======================================
215 */
216
217 // first get the http-path to typo3:
218 $this->httpTypo3Path = substr( substr( t3lib_div::getIndpEnv('TYPO3_SITE_URL'), strlen( t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') ) ), 0, -1 );
219 if (strlen($this->httpTypo3Path) == 1) {
220 $this->httpTypo3Path = '/';
221 } else {
222 $this->httpTypo3Path .= '/';
223 }
224 // Get the path to this extension:
225 $this->extHttpPath = $this->httpTypo3Path . t3lib_extMgm::siteRelPath($this->ID);
226 // Get the site URL
227 $this->siteURL = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
228 // Get the host URL
229 $this->hostURL = t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST');
230
231 // Element ID + pid
232 $this->elementId = $PA['itemFormElName']; // Form element name
233 $this->elementParts = explode('][',ereg_replace('\]$','',ereg_replace('^(TSFE_EDIT\[data\]\[|data\[)','',$this->elementId)));
234
235 // Find the page PIDs:
236 list($this->tscPID,$this->thePid) = t3lib_BEfunc::getTSCpid(trim($this->elementParts[0]),trim($this->elementParts[1]),$thePidValue);
237
238 // Record "types" field value:
239 $this->typeVal = $RTEtypeVal; // TCA "types" value for record
240
241 // Find "thisConfig" for record/editor:
242 unset($this->RTEsetup);
243 $this->RTEsetup = $BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($this->tscPID));
244 $this->thisConfig = $thisConfig;
245
246 // Special configuration and default extras:
247 $this->specConf = $specConf;
248
249 if ($this->thisConfig['forceHTTPS']) {
250 $this->httpTypo3Path = preg_replace('/^(http|https)/', 'https', $this->httpTypo3Path);
251 $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
252 $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
253 $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
254 }
255
256 /* =======================================
257 * LANGUAGES & CHARACTER SETS
258 * =======================================
259 */
260
261 // Languages: interface and content
262 $this->language = $LANG->lang;
263 if ($this->language=='default' || !$this->language) {
264 $this->language='en';
265 }
266 $this->contentTypo3Language = $this->language;
267 $this->contentISOLanguage = 'en';
268 $this->contentLanguageUid = ($row['sys_language_uid'] > 0) ? $row['sys_language_uid'] : 0;
269 if (t3lib_extMgm::isLoaded('static_info_tables')) {
270 if ($this->contentLanguageUid) {
271 $tableA = 'sys_language';
272 $tableB = 'static_languages';
273 $languagesUidsList = $this->contentLanguageUid;
274 $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2,' . $tableB . '.lg_typo3';
275 $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
276 $whereClause = $tableA . '.uid IN (' . $languagesUidsList . ') ';
277 $whereClause .= t3lib_BEfunc::BEenableFields($tableA);
278 $whereClause .= t3lib_BEfunc::deleteClause($tableA);
279 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
280 while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
281 $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']).(trim($languageRow['lg_country_iso_2'])?'_'.trim($languageRow['lg_country_iso_2']):''));
282 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
283 }
284 } else {
285 $this->contentISOLanguage = trim($this->thisConfig['defaultContentLanguage']) ? trim($this->thisConfig['defaultContentLanguage']) : 'en';
286 $selectFields = 'lg_iso_2, lg_typo3';
287 $tableAB = 'static_languages';
288 $whereClause = 'lg_iso_2 = ' . $TYPO3_DB->fullQuoteStr(strtoupper($this->contentISOLanguage), $tableAB);
289 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
290 while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
291 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
292 }
293 }
294 }
295
296 // Character sets: interface and content
297 $this->charset = $LANG->charSet;
298 $this->OutputCharset = $this->charset;
299
300 $this->contentCharset = $LANG->csConvObj->charSetArray[$this->contentTypo3Language];
301 $this->contentCharset = $this->contentCharset ? $this->contentCharset : 'iso-8859-1';
302 $this->origContentCharSet = $this->contentCharset;
303 $this->contentCharset = (trim($TYPO3_CONF_VARS['BE']['forceCharset']) ? trim($TYPO3_CONF_VARS['BE']['forceCharset']) : $this->contentCharset);
304
305 /* =======================================
306 * TOOLBAR CONFIGURATION
307 * =======================================
308 */
309 $this->initializeToolbarConfiguration();
310
311 /* =======================================
312 * SET STYLES
313 * =======================================
314 */
315
316 $RTEWidth = isset($BE_USER->userTS['options.']['RTESmallWidth']) ? $BE_USER->userTS['options.']['RTESmallWidth'] : '530';
317 $RTEHeight = isset($BE_USER->userTS['options.']['RTESmallHeight']) ? $BE_USER->userTS['options.']['RTESmallHeight'] : '380';
318 $RTEWidth = $RTEWidth + ($this->TCEform->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeWidthIncrement']) ? $BE_USER->userTS['options.']['RTELargeWidthIncrement'] : '150') : 0);
319 $RTEWidth -= ($inline->getStructureDepth() > 0 ? ($inline->getStructureDepth()+1)*$inline->getLevelMargin() : 0);
320 if (isset($this->thisConfig['RTEWidthOverride'])) {
321 if (strstr($this->thisConfig['RTEWidthOverride'], '%')) {
322 if ($this->client['BROWSER'] != 'msie') {
323 $RTEWidth = (intval($this->thisConfig['RTEWidthOverride']) > 0) ? $this->thisConfig['RTEWidthOverride'] : '100%';
324 }
325 } else {
326 $RTEWidth = (intval($this->thisConfig['RTEWidthOverride']) > 0) ? intval($this->thisConfig['RTEWidthOverride']) : $RTEWidth;
327 }
328 }
329 $RTEWidth = strstr($RTEWidth, '%') ? $RTEWidth : $RTEWidth . 'px';
330 $RTEHeight = $RTEHeight + ($this->TCEform->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeHeightIncrement']) ? $BE_USER->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
331 $RTEHeightOverride = intval($this->thisConfig['RTEHeightOverride']);
332 $RTEHeight = ($RTEHeightOverride > 0) ? $RTEHeightOverride : $RTEHeight;
333 $editorWrapWidth = '99%';
334 $editorWrapHeight = '100%';
335 $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:'.$RTEWidth.'; border: 1px solid black; padding: 2px 2px 2px 2px;';
336
337 /* =======================================
338 * LOAD CSS AND JAVASCRIPT
339 * =======================================
340 */
341 // Preloading the pageStyle and including RTE skin stylesheets
342 $this->addPageStyle();
343 $this->addSkin();
344
345 // Loading JavaScript files and code
346 if ($this->TCEform->RTEcounter == 1) {
347 $this->TCEform->additionalCode_pre['rtehtmlarea-loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter);
348 $this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
349 }
350
351 /* =======================================
352 * DRAW THE EDITOR
353 * =======================================
354 */
355
356 // Transform value:
357 $value = $this->transformContent('rte',$PA['itemFormElValue'],$table,$field,$row,$specConf,$thisConfig,$RTErelPath,$thePidValue);
358
359 // Further content transformation by registered plugins
360 foreach ($this->registeredPlugins as $pluginId => $plugin) {
361 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "transformContent")) {
362 $value = $plugin->transformContent($value);
363 }
364 }
365 // Register RTE windows
366 $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
367 $textAreaId = htmlspecialchars($PA['itemFormElName']);
368
369 // Check if wizard_rte called this for fullscreen edtition; if so, change the size of the RTE to fullscreen using JS
370 if (basename(PATH_thisScript) == 'wizard_rte.php') {
371 $height = 'window.innerHeight';
372 $width = 'window.innerWidth';
373 if ($this->client['BROWSER'] == 'msie') {
374 $height = 'document.body.offsetHeight';
375 $width = 'document.body.offsetWidth';
376 }
377
378 // Subtract the docheader height from the calculated window height
379 $height .= ' - document.getElementById("typo3-docheader").offsetHeight';
380
381 $editorWrapWidth = '100%';
382 $editorWrapHeight = '100%';
383 $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border: 1px solid black; padding: 2px 0px 2px 2px;';
384 $this->TCEform->additionalJS_post[] = $this->setRTEsizeByJS('RTEarea' . $textAreaId, $height, $width);
385 }
386
387 // Register RTE in JS:
388 $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
389
390 // Set the save option for the RTE:
391 $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
392 $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
393
394 // Draw the textarea
395 $visibility = 'hidden';
396 $item = $this->triggerField($PA['itemFormElName']).'
397 <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $LANG->getLL('Please wait') . '</div>
398 <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:' . $editorWrapHeight . ';">
399 <textarea id="RTEarea' . $textAreaId . '" name="'.htmlspecialchars($PA['itemFormElName']).'" style="'.t3lib_div::deHSCentities(htmlspecialchars($this->RTEdivStyle)).'">'.t3lib_div::formatForTextarea($value).'</textarea>
400 </div>' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableDebugMode'] ? '<div id="HTMLAreaLog"></div>' : '') . '
401 ';
402 }
403
404 // Return form item:
405 return $item;
406 }
407
408 /**
409 * Add link to content style sheet to document header
410 *
411 * @return void
412 */
413 protected function addPageStyle() {
414 // Get stylesheet file name from Page TSConfig if any
415 $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
416 $this->addStyleSheet(
417 'rtehtmlarea-page-style',
418 $this->getFullFileName($filename),
419 'htmlArea RTE Content CSS',
420 'alternate stylesheet'
421 );
422 }
423
424 /**
425 * Add links to skin style sheet(s) to document header
426 *
427 * @return void
428 */
429 protected function addSkin() {
430 // Get skin file name from Page TSConfig if any
431 $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
432 if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3' && substr($skinFilename,0,4) == 'EXT:') {
433 $skinFilename = 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
434 }
435 // Skin provided by some extension
436 if (substr($skinFilename,0,4) == 'EXT:') {
437 list($extKey,$local) = explode('/',substr($skinFilename,4),2);
438 $skinFilename='';
439 if (strcmp($extKey,'') && t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
440 $skinFilename = $this->httpTypo3Path . t3lib_extMgm::siteRelPath($extKey) . $local;
441 $skinDir = $this->siteURL . t3lib_extMgm::siteRelPath($extKey) . dirname($local);
442 }
443 } elseif (substr($skinFilename,0,1) != '/') {
444 $skinDir = $this->siteURL.dirname($skinFilename);
445 $skinFilename = $this->siteURL . $skinFilename;
446 } else {
447 $skinDir = substr($this->siteURL,0,-1) . dirname($skinFilename);
448 }
449 $this->editorCSS = $skinFilename;
450 // Editing area style sheet
451 $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
452 $this->addStyleSheet(
453 'rtehtmlarea-editing-area-skin',
454 $this->editedContentCSS
455 );
456 // Main skin
457 $this->addStyleSheet(
458 'rtehtmlarea-skin',
459 $this->editorCSS
460 );
461 // Additional icons from registered plugins
462 foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
463 if (is_object($this->registeredPlugins[$pluginId])) {
464 $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
465 if ($pathToSkin) {
466 $this->addStyleSheet(
467 'rtehtmlarea-plugin-' . $pluginId . '-skin',
468 $this->httpTypo3Path . t3lib_extMgm::siteRelPath($this->registeredPlugins[$pluginId]->getExtensionKey()) . $pathToSkin
469 );
470 }
471 }
472 }
473 }
474
475 /**
476 * Add style sheet file to document header
477 *
478 * @param string $key: some key identifying the style sheet
479 * @param string $href: uri to the style sheet file
480 * @param string $title: value for the title attribute of the link element
481 * @return string $relation: value for the rel attribute of the link element
482 * @return void
483 */
484 protected function addStyleSheet($key, $href, $title='', $relation='stylesheet') {
485 // If it was not known that an RTE-enabled would be created when the page was first created, the css would not be added to head
486 if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
487 $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title. '" />';
488 } else {
489 $this->TCEform->addStyleSheet($key, $href, $title, $relation);
490 }
491
492 }
493
494 /**
495 * Initialize toolbar configuration and enable registered plugins
496 *
497 * @return void
498 */
499 protected function initializeToolbarConfiguration() {
500
501 // Enable registred plugins
502 $this->enableRegisteredPlugins();
503
504 // Configure toolbar
505 $this->setToolbar();
506
507 // Check if some plugins need to be disabled
508 $this->setPlugins();
509
510 // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
511 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
512 if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])) {
513 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray,$this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])));
514 }
515 }
516
517 /**
518 * Add registered plugins to the array of enabled plugins
519 *
520 */
521 function enableRegisteredPlugins() {
522 global $TYPO3_CONF_VARS;
523 // Traverse registered plugins
524 if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
525 foreach($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
526 $plugin = false;
527 if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
528 $plugin = &t3lib_div::getUserObj($pluginObjectConfiguration['objectReference']);
529 }
530 if (is_object($plugin)) {
531 if ($plugin->main($this)) {
532 $this->registeredPlugins[$pluginId] = $plugin;
533 // Override buttons from previously registered plugins
534 $pluginButtons = t3lib_div::trimExplode(',', $plugin->getPluginButtons(), 1);
535 foreach ($this->pluginButton as $previousPluginId => $buttonList) {
536 $this->pluginButton[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginButton[$previousPluginId], 1), $pluginButtons));
537 }
538 $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
539 $pluginLabels = t3lib_div::trimExplode(',', $plugin->getPluginLabels(), 1);
540 foreach ($this->pluginLabel as $previousPluginId => $labelList) {
541 $this->pluginLabel[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginLabel[$previousPluginId], 1), $pluginLabels));
542 }
543 $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
544 $this->pluginEnabledArray[] = $pluginId;
545 }
546 }
547 }
548 }
549 // Process overrides
550 $hidePlugins = array();
551 foreach ($this->registeredPlugins as $pluginId => $plugin) {
552 if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
553 $hidePlugins[] = $pluginId;
554 }
555 }
556 $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
557 }
558
559 /**
560 * Set the toolbar config (only in this PHP-Object, not in JS):
561 *
562 */
563
564 function setToolbar() {
565 global $BE_USER;
566
567 if ($this->client['BROWSER'] == 'msie' || $this->client['BROWSER'] == 'opera' || ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')) {
568 $this->thisConfig['keepButtonGroupTogether'] = 0;
569 }
570
571 $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
572 bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
573 bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote,
574 bar, left, center, right, justifyfull,
575 bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
576 bar, textcolor, bgcolor, textindicator,
577 bar, emoticon, insertcharacter, line, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
578 bar, chMode, inserttag, removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
579 ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
580 columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
581 cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
582
583 // Special toolbar for Mozilla Wamcom on Mac OS 9
584 if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3') {
585 $this->defaultToolbarOrder = $this->TCEform->docLarge ? 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
586 bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
587 subscript, superscript, lefttoright, righttoleft, language, showlanguagemarks, bar, left, center, right, justifyfull, linebreak,
588 bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
589 insertcharacter, line, link, unlink, image, table, user, acronym, bar, findreplace, spellcheck, bar, chMode, inserttag,
590 removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
591 bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
592 columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
593 cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge'
594 : 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
595 bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
596 subscript, superscript, linebreak, bar, lefttoright, righttoleft, language, showlanguagemarks, bar, left, center, right, justifyfull,
597 orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
598 insertcharacter, line, link, unlink, image, table, user, acronym, linebreak, bar, findreplace, spellcheck, bar, chMode, inserttag,
599 removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
600 bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
601 columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
602 cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
603 }
604
605 // Additional buttons from registered plugins
606 foreach($this->registeredPlugins as $pluginId => $plugin) {
607 if ($this->isPluginEnabled($pluginId)) {
608 $this->defaultToolbarOrder = $plugin->addButtonsToToolbar();
609 }
610 }
611 $toolbarOrder = $this->thisConfig['toolbarOrder'] ? $this->thisConfig['toolbarOrder'] : $this->defaultToolbarOrder;
612
613 // Getting rid of undefined buttons
614 $this->toolbarOrderArray = array_intersect(t3lib_div::trimExplode(',', $toolbarOrder, 1), t3lib_div::trimExplode(',', $this->defaultToolbarOrder, 1));
615 $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
616
617 // Fetching specConf for field from backend
618 $pList = is_array($this->specConf['richtext']['parameters']) ? implode(',',$this->specConf['richtext']['parameters']) : '';
619 if ($pList != '*') { // If not all
620 $show = is_array($this->specConf['richtext']['parameters']) ? $this->specConf['richtext']['parameters'] : array();
621 if ($this->thisConfig['showButtons']) {
622 if (!t3lib_div::inList($this->thisConfig['showButtons'],'*')) {
623 $show = array_unique(array_merge($show,t3lib_div::trimExplode(',',$this->thisConfig['showButtons'],1)));
624 } else {
625 $show = array_unique(array_merge($show, $toolbarOrder));
626 }
627 }
628 if (is_array($this->thisConfig['showButtons.'])) {
629 foreach ($this->thisConfig['showButtons.'] as $buttonId => $value) {
630 if ($value) $show[] = $buttonId;
631 }
632 $show = array_unique($show);
633 }
634 } else {
635 $show = $toolbarOrder;
636 }
637
638 // Resticting to RTEkeyList for backend user
639 if(is_object($BE_USER)) {
640 $RTEkeyList = isset($BE_USER->userTS['options.']['RTEkeyList']) ? $BE_USER->userTS['options.']['RTEkeyList'] : '*';
641 if ($RTEkeyList != '*') { // If not all
642 $show = array_intersect($show, t3lib_div::trimExplode(',',$RTEkeyList,1));
643 }
644 }
645
646 // Hiding buttons of disabled plugins
647 $hideButtons = array('space', 'bar', 'linebreak');
648 foreach ($this->pluginButton as $pluginId => $buttonList) {
649 if (!$this->isPluginEnabled($pluginId)) {
650 $buttonArray = t3lib_div::trimExplode(',',$buttonList,1);
651 foreach ($buttonArray as $button) {
652 $hideButtons[] = $button;
653 }
654 }
655 }
656
657 // Hiding labels of disabled plugins
658 foreach ($this->pluginLabel as $pluginId => $label) {
659 if (!$this->isPluginEnabled($pluginId)) {
660 $hideButtons[] = $label;
661 }
662 }
663
664 // Hiding buttons
665 $show = array_diff($show, $this->conf_toolbar_hide, t3lib_div::trimExplode(',',$this->thisConfig['hideButtons'],1));
666
667 // Apply toolbar constraints from registered plugins
668 foreach ($this->registeredPlugins as $pluginId => $plugin) {
669 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "applyToolbarConstraints")) {
670 $show = $plugin->applyToolbarConstraints($show);
671 }
672 }
673 // Getting rid of the buttons for which we have no position
674 $show = array_intersect($show, $toolbarOrder);
675 $this->toolbar = $show;
676 }
677
678 /**
679 * Disable some plugins
680 *
681 */
682 function setPlugins() {
683
684 // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
685 $hidePlugins = array();
686 foreach ($this->pluginButton as $pluginId => $buttonList) {
687 if ($this->registeredPlugins[$pluginId]->addsButtons()) {
688 $showPlugin = false;
689 $buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
690 foreach ($buttonArray as $button) {
691 if (in_array($button, $this->toolbar)) {
692 $showPlugin = true;
693 }
694 }
695 if (!$showPlugin) {
696 $hidePlugins[] = $pluginId;
697 }
698 }
699 }
700 $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
701
702 // Hiding labels of disabled plugins
703 $hideLabels = array();
704 foreach ($this->pluginLabel as $pluginId => $label) {
705 if (!$this->isPluginEnabled($pluginId)) {
706 $hideLabels[] = $label;
707 }
708 }
709 $this->toolbar = array_diff($this->toolbar, $hideLabels);
710
711 // Adding plugins declared as prerequisites by enabled plugins
712 $requiredPlugins = array();
713 foreach ($this->registeredPlugins as $pluginId => $plugin) {
714 if ($this->isPluginEnabled($pluginId)) {
715 $requiredPlugins = array_merge($requiredPlugins, t3lib_div::trimExplode(',', $plugin->getRequiredPlugins(), 1));
716 }
717 }
718 $requiredPlugins = array_unique($requiredPlugins);
719 foreach ($requiredPlugins as $pluginId) {
720 if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
721 $this->pluginEnabledArray[] = $pluginId;
722 }
723 }
724 $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
725
726 // Completing the toolbar conversion array for htmlArea
727 foreach ($this->registeredPlugins as $pluginId => $plugin) {
728 if ($this->isPluginEnabled($pluginId)) {
729 $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
730 }
731 }
732 }
733
734 /**
735 * Convert the TYPO3 names of buttons into the names for htmlArea RTE
736 *
737 * @param string buttonname (typo3-name)
738 * @return string buttonname (htmlarea-name)
739 */
740
741 function convertToolbarForHTMLArea($button) {
742 return $this->convertToolbarForHtmlAreaArray[$button];
743 }
744
745 /**
746 * Return the JS-function for setting the RTE size.
747 *
748 * @param string DivID-Name
749 * @param int the height for the RTE
750 * @param int the width for the RTE
751 * @return string Loader function in JS
752 */
753 function setRTEsizeByJS($divId, $height, $width) {
754 return '
755 setRTEsizeByJS(\''.$divId.'\','.$height.', '.$width.');
756 ';
757 }
758
759 /**
760 * Return the HTML code for loading the Javascript files
761 *
762 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
763 *
764 * @return string the html code for loading the Javascript Files
765 */
766 function loadJSfiles($RTEcounter) {
767 global $TYPO3_CONF_VARS;
768
769 $loadPluginCode = '
770 HTMLArea_plugins = new Array();';
771 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
772 $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
773 $loadPluginCode .= '
774 HTMLArea_plugins.push({url : "' . $this->writeTemporaryFile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', "$1".'-'."$2"."$3", $pluginId)) . '.js', $pluginId) . '", asynchronous : ' . ($this->registeredPlugins[$pluginId]->requiresSynchronousLoad() ? 'false' : 'true'). ' });';
775 }
776 // Avoid re-initialization on AJax call when RTEarea object was already initialized
777 $loadJavascriptCode = '
778 <script type="text/javascript">
779 /*<![CDATA[*/
780 if (typeof(RTEarea) == "undefined") {
781 RTEarea = new Object();
782 RTEarea.init = function() {
783 if (typeof(HTMLArea) == "undefined") {
784 window.setTimeout("RTEarea.init();", 40);
785 } else {'
786 . $loadPluginCode . '
787 HTMLArea.init();
788 }
789 };
790 RTEarea.initEditor = function(editorNumber) {
791 if (typeof(HTMLArea) == "undefined") {
792 window.setTimeout("RTEarea.initEditor(\'" + editorNumber + "\');", 40);
793 } else {
794 HTMLArea.initEditor(editorNumber);
795 }
796 };
797 RTEarea[0] = new Object();
798 RTEarea[0].version = "' . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . '";'
799 . (($this->client['BROWSER'] == 'msie') ? ('
800 RTEarea[0]["htmlarea-ie"] = "' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-ie.js', "htmlarea-ie") . '";')
801 : ('
802 RTEarea[0]["htmlarea-gecko"] = "' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-gecko.js', "htmlarea-gecko") . '";')) . '
803 _editor_url = "' . $this->extHttpPath . 'htmlarea";
804 _editor_lang = "' . $this->language . '";
805 _editor_CSS = "' . $this->editorCSS . '";
806 _editor_skin = "' . dirname($this->editorCSS) . '";
807 _editor_edited_content_CSS = "' . $this->editedContentCSS . '";
808 _typo3_host_url = "' . $this->hostURL . '";
809 _editor_debug_mode = ' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableDebugMode'] ? 'true' : 'false') . ';
810 _editor_compressed_scripts = ' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] ? 'true' : 'false') . ';
811 }
812 /*]]>*/
813 </script>';
814 $loadJavascriptCode .= '
815 <script type="text/javascript" src="' . $this->buildJSMainLangFile($RTEcounter) . '"></script>
816 <script type="text/javascript" src="' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea.js', "htmlarea") . '"></script>
817 ';
818 return $loadJavascriptCode;
819 }
820
821 /**
822 * Return the Javascript code for initializing the RTE
823 *
824 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
825 *
826 * @return string the Javascript code for initializing the RTE
827 */
828 function loadJScode($RTEcounter) {
829 return (!$this->is_FE() ? '' : '
830 ' . '/*<![CDATA[*/') . '
831 RTEarea.init();' . (!$this->is_FE() ? '' : '
832 /*]]>*/
833 ');
834 }
835
836 /**
837 * Return the Javascript code for configuring the RTE
838 *
839 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
840 * @param string $table: The table that includes this RTE (optional, necessary for IRRE).
841 * @param string $uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
842 * @param string $field: The field of that record that includes this RTE (optional).
843 *
844 * @return string the Javascript code for configuring the RTE
845 */
846 function registerRTEinJS($RTEcounter, $table='', $uid='', $field='', $textAreaId = '') {
847 global $TYPO3_CONF_VARS;
848
849 $configureRTEInJavascriptString = (!$this->is_FE() ? '' : '
850 ' . '/*<![CDATA[*/') . '
851 if (typeof(configureEditorInstance) == "undefined") {
852 configureEditorInstance = new Object();
853 }
854 configureEditorInstance["' . $textAreaId . '"] = function() {
855 if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
856 window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
857 } else {
858 editornumber = "' . $textAreaId . '";
859 RTEarea[editornumber] = new Object();
860 RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
861 RTEarea[editornumber].number = editornumber;
862 RTEarea[editornumber].deleted = false;
863 RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
864 RTEarea[editornumber].id = "RTEarea" + editornumber;
865 RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean'])?'true':'false') . ';
866 RTEarea[editornumber]["htmlRemoveComments"] = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . ';
867 RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . ';
868 RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing'])?'true':'false') . ';
869 RTEarea[editornumber]["removeTrailingBR"] = ' . (trim($this->thisConfig['removeTrailingBR'])?'true':'false') . ';
870 RTEarea[editornumber]["useCSS"] = ' . (trim($this->thisConfig['useCSS'])?'true':'false') . ';
871 RTEarea[editornumber]["keepButtonGroupTogether"] = ' . (trim($this->thisConfig['keepButtonGroupTogether'])?'true':'false') . ';
872 RTEarea[editornumber]["disablePCexamples"] = ' . (trim($this->thisConfig['disablePCexamples'])?'true':'false') . ';
873 RTEarea[editornumber]["showTagFreeClasses"] = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
874 RTEarea[editornumber]["useHTTPS"] = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
875 RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(true) : '[]') . ';
876 RTEarea[editornumber].dialogueWindows = new Object();
877 RTEarea[editornumber].dialogueWindows.defaultPositionFromTop = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) : '100') . ';
878 RTEarea[editornumber].dialogueWindows.defaultPositionFromLeft = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) : '100') . ';
879 RTEarea[editornumber].dialogueWindows.doNotResize = ' . (trim($this->thisConfig['dialogueWindows.']['doNotResize'])?'true':'false') . ';
880 RTEarea[editornumber].dialogueWindows.doNotCenter = ' . (trim($this->thisConfig['dialogueWindows.']['doNotCenter'])?'true':'false') . ';';
881
882 // The following properties apply only to the backend
883 if (!$this->is_FE()) {
884 $configureRTEInJavascriptString .= '
885 RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
886 RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
887 RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
888 RTEarea[editornumber].userUid = "' . $this->userUid . '";';
889 }
890
891 // Setting the plugin flags
892 $configureRTEInJavascriptString .= '
893 RTEarea[editornumber].plugin = new Object();
894 RTEarea[editornumber].pathToPluginDirectory = new Object();';
895 foreach ($this->pluginEnabledArray as $pluginId) {
896 $configureRTEInJavascriptString .= '
897 RTEarea[editornumber].plugin.'.$pluginId.' = true;';
898 if (is_object($this->registeredPlugins[$pluginId])) {
899 $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
900 if ($pathToPluginDirectory) {
901 $configureRTEInJavascriptString .= '
902 RTEarea[editornumber].pathToPluginDirectory.'.$pluginId.' = "' . $pathToPluginDirectory . '";';
903 }
904 }
905 }
906
907 // Setting the buttons configuration
908 $configureRTEInJavascriptString .= '
909 RTEarea[editornumber].buttons = new Object();';
910 if (is_array($this->thisConfig['buttons.'])) {
911 foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
912 $button = substr($buttonIndex, 0, -1);
913 if (in_array($button,$this->toolbar)) {
914 $configureRTEInJavascriptString .= '
915 RTEarea[editornumber].buttons.'.$button.' = ' . $this->buildNestedJSArray($conf) . ';';
916 }
917 }
918 }
919
920 // Setting the list of tags to be removed if specified in the RTE config
921 if (trim($this->thisConfig['removeTags'])) {
922 $configureRTEInJavascriptString .= '
923 RTEarea[editornumber]["htmlRemoveTags"] = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
924 }
925
926 // Setting the list of tags to be removed with their contents if specified in the RTE config
927 if (trim($this->thisConfig['removeTagsAndContents'])) {
928 $configureRTEInJavascriptString .= '
929 RTEarea[editornumber]["htmlRemoveTagsAndContents"] = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
930 }
931
932 // Process default style configuration
933 $configureRTEInJavascriptString .= '
934 RTEarea[editornumber].defaultPageStyle = "' . $this->hostURL . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
935
936 // Setting the pageStyle
937 $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
938 $configureRTEInJavascriptString .= '
939 RTEarea[editornumber].pageStyle = "' . $this->getFullFileName($filename) .'";';
940
941 // Process classes configuration
942 $classesConfigurationRequired = false;
943 foreach ($this->registeredPlugins as $pluginId => $plugin) {
944 if ($this->isPluginEnabled($pluginId)) {
945 $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
946 }
947 }
948 if ($classesConfigurationRequired) {
949 $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
950 }
951
952 // Add Javascript configuration for registered plugins
953 foreach ($this->registeredPlugins as $pluginId => $plugin) {
954 if ($this->isPluginEnabled($pluginId)) {
955 $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
956 }
957 }
958 // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
959 $configureRTEInJavascriptString .= '
960 RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
961 RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
962 RTEarea.initEditor(editornumber);
963 }
964 };
965 configureEditorInstance["' . $textAreaId . '"]();'. (!$this->is_FE() ? '' : '
966 /*]]>*/');
967 return $configureRTEInJavascriptString;
968 }
969
970 /**
971 * Return true, if the plugin can be loaded
972 *
973 * @param string $pluginId: The identification string of the plugin
974 *
975 * @return boolean true if the plugin can be loaded
976 */
977
978 function isPluginEnabled($pluginId) {
979 return in_array($pluginId, $this->pluginEnabledArray);
980 }
981
982 /**
983 * Build the default content style sheet
984 *
985 * @return string Style sheet
986 */
987 function buildStyleSheet() {
988
989 if (!trim($this->thisConfig['ignoreMainStyleOverride'])) {
990 $mainStyle_font = $this->thisConfig['mainStyle_font'] ? $this->thisConfig['mainStyle_font']: 'Verdana,sans-serif';
991
992 $mainElements = array();
993 $mainElements['P'] = $this->thisConfig['mainStyleOverride_add.']['P'];
994 $elList = explode(',','H1,H2,H3,H4,H5,H6,PRE');
995 foreach ($elList as $elListName) {
996 if ($this->thisConfig['mainStyleOverride_add.'][$elListName]) {
997 $mainElements[$elListName] = $this->thisConfig['mainStyleOverride_add.'][$elListName];
998 }
999 }
1000
1001 $addElementCode = '';
1002 foreach ($mainElements as $elListName => $elValue) {
1003 $addElementCode .= strToLower($elListName) . ' {' . $elValue . '}' . chr(10);
1004 }
1005
1006 $stylesheet = $this->thisConfig['mainStyleOverride'] ? $this->thisConfig['mainStyleOverride'] : chr(10) .
1007 'body.htmlarea-content-body { font-family: ' . $mainStyle_font .
1008 '; font-size: '.($this->thisConfig['mainStyle_size'] ? $this->thisConfig['mainStyle_size'] : '12px') .
1009 '; color: '.($this->thisConfig['mainStyle_color']?$this->thisConfig['mainStyle_color'] : 'black') .
1010 '; background-color: '.($this->thisConfig['mainStyle_bgcolor'] ? $this->thisConfig['mainStyle_bgcolor'] : 'white') .
1011 ';'.$this->thisConfig['mainStyleOverride_add.']['BODY'].'}' . chr(10) .
1012 'td { ' . $this->thisConfig['mainStyleOverride_add.']['TD'].'}' . chr(10) .
1013 'div { ' . $this->thisConfig['mainStyleOverride_add.']['DIV'].'}' . chr(10) .
1014 'pre { ' . $this->thisConfig['mainStyleOverride_add.']['PRE'].'}' . chr(10) .
1015 'ol { ' . $this->thisConfig['mainStyleOverride_add.']['OL'].'}' . chr(10) .
1016 'ul { ' . $this->thisConfig['mainStyleOverride_add.']['UL'].'}' . chr(10) .
1017 'blockquote { ' . $this->thisConfig['mainStyleOverride_add.']['BLOCKQUOTE'].'}' . chr(10) .
1018 $addElementCode;
1019
1020 if (is_array($this->thisConfig['inlineStyle.'])) {
1021 $stylesheet .= chr(10) . implode(chr(10), $this->thisConfig['inlineStyle.']) . chr(10);
1022 }
1023 } else {
1024 $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
1025 }
1026 return $stylesheet;
1027 }
1028
1029 /**
1030 * Return Javascript configuration of classes
1031 *
1032 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1033 *
1034 * @return string Javascript configuration of classes
1035 */
1036 function buildJSClassesConfig($RTEcounter) {
1037 // Build JS array of lists of classes
1038 $classesTagList = 'classesCharacter, classesParagraph, classesImage, classesTable, classesLinks, classesTD';
1039 $classesTagConvert = array( 'classesCharacter' => 'span', 'classesParagraph' => 'div', 'classesImage' => 'img', 'classesTable' => 'table', 'classesLinks' => 'a', 'classesTD' => 'td');
1040 $classesTagArray = t3lib_div::trimExplode(',' , $classesTagList);
1041 $configureRTEInJavascriptString = '
1042 RTEarea[editornumber]["classesTag"] = new Object();';
1043 foreach ($classesTagArray as $classesTagName) {
1044 $HTMLAreaJSClasses = ($this->thisConfig[$classesTagName])?('"' . $this->cleanList($this->thisConfig[$classesTagName]) . '";'):'null;';
1045 $configureRTEInJavascriptString .= '
1046 RTEarea[editornumber]["classesTag"]["'. $classesTagConvert[$classesTagName] .'"] = '. $HTMLAreaJSClasses;
1047 }
1048
1049 // Include JS arrays of configured classes
1050 $configureRTEInJavascriptString .= '
1051 RTEarea[editornumber]["classesUrl"] = "' . $this->hostURL . $this->writeTemporaryFile('', 'classes_'.$LANG->lang, 'js', $this->buildJSClassesArray()) . '";';
1052
1053 return $configureRTEInJavascriptString;
1054 }
1055
1056 /**
1057 * Return JS arrays of classes configuration
1058 *
1059 * @return string JS classes arrays
1060 */
1061 function buildJSClassesArray() {
1062 if ($this->is_FE()) {
1063 $RTEProperties = $this->RTEsetup;
1064 } else {
1065 $RTEProperties = $this->RTEsetup['properties'];
1066 }
1067 $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
1068 $JSClassesArray = '';
1069 // Scanning the list of classes if specified in the RTE config
1070 if (is_array($RTEProperties['classes.'])) {
1071 foreach ($RTEProperties['classes.'] as $className => $conf) {
1072 $className = rtrim($className, '.');
1073 $classesArray['labels'][$className] = $this->getPageConfigLabel($conf['name'], FALSE);
1074 $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
1075 if (isset($conf['noShow'])) {
1076 $classesArray['noShow'][$className] = $conf['noShow'];
1077 }
1078 if (is_array($conf['alternating.'])) {
1079 $classesArray['alternating'][$className] = $conf['alternating.'];
1080 }
1081 if (is_array($conf['counting.'])) {
1082 $classesArray['counting'][$className] = $conf['counting.'];
1083 }
1084 }
1085 }
1086 // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
1087 if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
1088 foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
1089 $classSet = t3lib_div::trimExplode(',', $conf, 1);
1090 $classList = implode(',', $classSet);
1091 foreach ($classSet as $className) {
1092 $classesArray['XOR'][$className] = '/^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $classList), 1)) . ')$/';
1093 }
1094 }
1095 }
1096 foreach ($classesArray as $key => $subArray) {
1097 $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . chr(10);
1098 }
1099 return $JSClassesArray;
1100 }
1101
1102 /**
1103 * Translate Page TS Config array in JS nested array definition
1104 * Replace 0 values with false
1105 * Unquote regular expression values
1106 * Replace empty arrays with empty objects
1107 *
1108 * @param array $conf: Page TSConfig configuration array
1109 *
1110 * @return string nested JS array definition
1111 */
1112 function buildNestedJSArray($conf) {
1113 return str_replace(array(':"0"', ':"\/^(', ')$\/i"', ':"\/^(', ')$\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode(t3lib_div::removeDotsFromTS($conf)));
1114 }
1115
1116 /**
1117 * Return a Javascript localization array for htmlArea RTE
1118 *
1119 * @return string Javascript localization array
1120 */
1121 function buildJSMainLangArray() {
1122 $JSLanguageArray = 'var HTMLArea_langArray = new Object();' . chr(10);
1123 $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
1124 foreach ($labelsArray as $labels => $subArray) {
1125 if ($this->is_FE()) {
1126 $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, $this->OutputCharset);
1127 } else {
1128 $LOCAL_LANG = $GLOBALS['LANG']->readLLfile(t3lib_extMgm::extPath($this->ID).'htmlarea/locallang_' . $labels . '.xml');
1129 }
1130 if (!empty($LOCAL_LANG[$this->language])) {
1131 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language]);
1132 } else {
1133 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1134 }
1135 $labelsArray[$labels] = $LOCAL_LANG[$this->language];
1136 }
1137 $JSLanguageArray .= 'HTMLArea_langArray = ' . json_encode($labelsArray) . ';' . chr(10);
1138 return $JSLanguageArray;
1139 }
1140
1141 /**
1142 * Writes contents in a file in typo3temp/rtehtmlarea directory and returns the file name
1143 *
1144 * @param string $sourceFileName: The name of the file from which the contents should be extracted
1145 * @param string $label: A label to insert at the beginning of the name of the file
1146 * @param string $fileExtension: The file extension of the file, defaulting to 'js'
1147 * @param string $contents: The contents to write into the file if no $sourceFileName is provided
1148 *
1149 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1150 */
1151 public function writeTemporaryFile($sourceFileName='', $label, $fileExtension='js', $contents='') {
1152 global $TYPO3_CONF_VARS;
1153
1154 if ($sourceFileName) {
1155 $output = '';
1156 $source = t3lib_div::getFileAbsFileName($sourceFileName);
1157 $output = file_get_contents($source);
1158 } else {
1159 $output = $contents;
1160 }
1161 $compress = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] && ($fileExtension == 'js') && ($output != '');
1162 $relativeFilename = 'typo3temp/' . $this->ID . '/' . str_replace('-','_',$label) . '_' . t3lib_div::shortMD5(($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName?$sourceFileName:$output)), 20) . ($compress ? '_compressed' : '') . '.' . $fileExtension;
1163 $destination = PATH_site . $relativeFilename;
1164 if(!file_exists($destination)) {
1165 $compressedJavaScript = '';
1166 if ($compress) {
1167 $compressedJavaScript = t3lib_div::minifyJavaScript($output);
1168 }
1169 $failure = t3lib_div::writeFileToTypo3tempDir($destination, $compressedJavaScript?$compressedJavaScript:$output);
1170 if ($failure) {
1171 die($failure);
1172 }
1173 }
1174 return ($this->thisConfig['forceHTTPS']?$this->siteURL:$this->httpTypo3Path) . $relativeFilename;
1175 }
1176
1177 /**
1178 * Return a file name containing the main JS language array for HTMLArea
1179 *
1180 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1181 *
1182 * @return string filename
1183 */
1184
1185 function buildJSMainLangFile($RTEcounter) {
1186 $contents = $this->buildJSMainLangArray() . chr(10);
1187 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
1188 $contents .= $this->buildJSLangArray($pluginId) . chr(10);
1189 }
1190 return $this->writeTemporaryFile('', $this->language.'_'.$this->OutputCharset, 'js', $contents);
1191 }
1192
1193 /**
1194 * Return a Javascript localization array for the plugin
1195 *
1196 * @param string $plugin: identification string of the plugin
1197 *
1198 * @return string Javascript localization array
1199 */
1200
1201 function buildJSLangArray($plugin) {
1202
1203 $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
1204 $linebreak = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : chr(10);
1205 $JSLanguageArray = '';
1206
1207 if ($this->is_FE()) {
1208 $fileRef = 'EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml';
1209 } else {
1210 $fileRef = t3lib_extMgm::extPath($extensionKey).'htmlarea/plugins/' . $plugin . '/locallang.xml';
1211 }
1212 $file = t3lib_div::getFileAbsFileName($fileRef);
1213 if (@is_file($file)) {
1214 if ($this->is_FE()) {
1215 $LOCAL_LANG = t3lib_div::readLLfile($fileRef, $this->language, $this->OutputCharset);
1216 } else {
1217 $LOCAL_LANG = $GLOBALS['LANG']->readLLfile(t3lib_extMgm::extPath($extensionKey).'htmlarea/plugins/' . $plugin . '/locallang.xml');
1218 }
1219 }
1220 if (is_array($LOCAL_LANG)) {
1221 if (!empty($LOCAL_LANG[$this->language])) {
1222 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'],$LOCAL_LANG[$this->language]);
1223 } else {
1224 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1225 }
1226 $JSLanguageArray .= 'var ' . $plugin . '_langArray = new Object();' . $linebreak;
1227 $JSLanguageArray .= $plugin . '_langArray = ' . json_encode($LOCAL_LANG[$this->language]) . ';'. chr(10);
1228 }
1229 return $JSLanguageArray;
1230 }
1231
1232 /**
1233 * Return the JS-Code for the Toolbar-Config-Array for HTML-Area
1234 *
1235 * @return string the JS-Code as an JS-Array
1236 */
1237
1238 function getJSToolbarArray() {
1239 $toolbar = ''; // The JS-Code for the toolbar
1240 $group = ''; // The TS-Code for the group in the moment, each group are between "bar"s
1241 $group_has_button = false; // True if the group has any enabled buttons
1242 $group_needs_starting_bar = false;
1243 $previous_is_space = false;
1244
1245 // process each button in the order list
1246 foreach ($this->toolbarOrderArray as $button) {
1247 // check if a new group starts
1248 if (($button == 'bar' || $button == 'linebreak') && $group_has_button) {
1249 // New line
1250 if ($button == 'linebreak') {
1251 $convertButton = '"' . $this->convertToolbarForHTMLArea('linebreak') . '"';
1252 $group = ($group!='') ? ($group . ', ' . $convertButton) : $convertButton;
1253 }
1254 // New group
1255 $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group);
1256 $group = '';
1257 $previous_is_space = false;
1258 $group_has_button = false;
1259 $group_needs_starting_bar = ($button == 'bar');
1260 } elseif ($toolbar && $button == 'linebreak' && !$group_has_button) {
1261 // Insert linebreak if no group is opened
1262 $group = '';
1263 $previous_is_space = false;
1264 $group_needs_starting_bar = false;
1265 $toolbar .= ', "' . $this->convertToolbarForHTMLArea($button) . '"';
1266 } elseif ($button == 'bar' && !$group_has_button) {
1267 $group_needs_starting_bar = true;
1268 } elseif ($button == 'space' && $group_has_button && !$previous_is_space) {
1269 $convertButton = $this->convertToolbarForHTMLArea($button);
1270 $convertButton = '"' . $convertButton . '"';
1271 $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton);
1272 $group_needs_starting_bar = false;
1273 $previous_is_space = true;
1274 } elseif (in_array($button, $this->toolbar)) {
1275 // Add the button to the group
1276 $convertButton = $this->convertToolbarForHTMLArea($button);
1277 if ($convertButton) {
1278 $convertButton = '"' . $convertButton . '"';
1279 $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton);
1280 $group_has_button = true;
1281 $group_needs_starting_bar = false;
1282 $previous_is_space = false;
1283 }
1284 }
1285 // else ignore
1286 }
1287 // add the last group
1288 if($group_has_button) $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group);
1289 $toolbar = $toolbar . ']]';
1290 return $toolbar;
1291 }
1292
1293 public function getLLContent($string) {
1294 global $LANG;
1295
1296 $BE_lang = $LANG->lang;
1297 $BE_charSet = $LANG->charSet;
1298 $LANG->lang = $this->contentTypo3Language;
1299 $LANG->charSet = $this->contentCharset;
1300 $LLString = $LANG->JScharCode($LANG->sL($string));
1301 $LANG->lang = $BE_lang;
1302 $LANG->charSet = $BE_charSet;
1303 return $LLString;
1304 }
1305
1306 public function getPageConfigLabel($string,$JScharCode=1) {
1307 global $LANG, $TSFE, $TYPO3_CONF_VARS;
1308
1309 if ($this->is_FE()) {
1310 if (strcmp(substr($string,0,4),'LLL:') && $TYPO3_CONF_VARS['BE']['forceCharset']) {
1311 // A pure string coming from Page TSConfig must be in forceCharset, otherwise we just don't know..
1312 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $TYPO3_CONF_VARS['BE']['forceCharset'], $this->OutputCharset);
1313 } else {
1314 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
1315 }
1316 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1317 $label = $JScharCode ? $this->feJScharCode($label) : $label;
1318 } else {
1319 if (strcmp(substr($string,0,4),'LLL:')) {
1320 $label = $string;
1321 } else {
1322 $label = $LANG->sL(trim($string));
1323 }
1324 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1325 $label = $JScharCode ? $LANG->JScharCode($label): $label;
1326 }
1327 return $label;
1328 }
1329
1330 function feJScharCode($str) {
1331 global $TSFE;
1332 // Convert string to UTF-8:
1333 if ($this->OutputCharset != 'utf-8') $str = $TSFE->csConvObj->utf8_encode($str,$this->OutputCharset);
1334 // Convert the UTF-8 string into a array of char numbers:
1335 $nArr = $TSFE->csConvObj->utf8_to_numberarray($str);
1336 return 'String.fromCharCode('.implode(',',$nArr).')';
1337 }
1338
1339 public function getFullFileName($filename) {
1340 if (substr($filename,0,4)=='EXT:') { // extension
1341 list($extKey,$local) = explode('/',substr($filename,4),2);
1342 $newFilename = '';
1343 if (strcmp($extKey,'') && t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
1344 $newFilename = $this->siteURL . t3lib_extMgm::siteRelPath($extKey) . $local;
1345 }
1346 } elseif (substr($filename,0,1) != '/') {
1347 $newFilename = $this->siteURL . $filename;
1348 } else {
1349 $newFilename = $this->siteURL . substr($filename,1);
1350 }
1351 return $newFilename;
1352 }
1353
1354 /**
1355 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1356 * This is for submit function of the form.
1357 *
1358 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1359 * @param string $formName: the name of the form
1360 * @param string $textareaId: the id of the textarea
1361 *
1362 * @return string Javascript code
1363 */
1364 function setSaveRTE($RTEcounter, $formName, $textareaId) {
1365 return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getPluginInstance("EditorMode").getHTML(); } else { OK = 0; };';
1366 }
1367
1368 /**
1369 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1370 * This is for submit function of the form.
1371 *
1372 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1373 * @param string $formName: the name of the form
1374 * @param string $textareaId: the id of the textarea
1375 *
1376 * @return string Javascript code
1377 */
1378 function setDeleteRTE($RTEcounter, $formName, $textareaId) {
1379 return 'if (RTEarea["' . $textareaId . '"]) { RTEarea["' . $textareaId . '"].deleted = true;}';
1380 }
1381
1382 /**
1383 * Return true if we are in the FE, but not in the FE editing feature of BE.
1384 *
1385 * @return boolean
1386 */
1387
1388 function is_FE() {
1389 global $TSFE;
1390 return is_object($TSFE) && is_array($this->LOCAL_LANG) && !strstr($this->elementId,'TSFE_EDIT');
1391 }
1392
1393 /**
1394 * Client Browser Information
1395 *
1396 * Usage: 4
1397 *
1398 * @param string Alternative User Agent string (if empty, t3lib_div::getIndpEnv('HTTP_USER_AGENT') is used)
1399 * @return array Parsed information about the HTTP_USER_AGENT in categories BROWSER, VERSION, SYSTEM and FORMSTYLE
1400 */
1401
1402 function clientInfo($useragent='') {
1403 global $TYPO3_CONF_VARS;
1404
1405 if (!$useragent) $useragent=t3lib_div::getIndpEnv('HTTP_USER_AGENT');
1406
1407 $bInfo=array();
1408 // Which browser?
1409 if (strstr($useragent,'Konqueror')) {
1410 $bInfo['BROWSER']= 'konqu';
1411 } elseif (strstr($useragent,'Opera')) {
1412 $bInfo['BROWSER']= 'opera';
1413 } elseif (strstr($useragent,'MSIE')) {
1414 $bInfo['BROWSER']= 'msie';
1415 } elseif (strstr($useragent,'Gecko/')) {
1416 $bInfo['BROWSER']='gecko';
1417 } elseif (strstr($useragent,'Safari/')) {
1418 $bInfo['BROWSER']='safari';
1419 } elseif (strstr($useragent,'Mozilla/4')) {
1420 $bInfo['BROWSER']='net';
1421 }
1422
1423 if ($bInfo['BROWSER']) {
1424 // Browser version
1425 switch($bInfo['BROWSER']) {
1426 case 'net':
1427 $bInfo['VERSION']= doubleval(substr($useragent,8));
1428 if (strstr($useragent,'Netscape6/')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape6/'),10));}
1429 if (strstr($useragent,'Netscape/7')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape/7'),9));}
1430 break;
1431 case 'gecko':
1432 $tmp = strstr($useragent,'rv:');
1433 $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,3)));
1434 break;
1435 case 'msie':
1436 $tmp = strstr($useragent,'MSIE');
1437 $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,4)));
1438 break;
1439 case 'safari':
1440 $tmp = strstr($useragent,'Safari/');
1441 $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,3)));
1442 break;
1443 case 'opera':
1444 $tmp = strstr($useragent,'Opera');
1445 $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,5)));
1446 break;
1447 case 'konqu':
1448 $tmp = strstr($useragent,'Konqueror/');
1449 $bInfo['VERSION'] = doubleval(substr($tmp,10));
1450 break;
1451 }
1452
1453 // Client system
1454 if (strstr($useragent,'Win')) {
1455 $bInfo['SYSTEM'] = 'win';
1456 } elseif (strstr($useragent,'Mac')) {
1457 $bInfo['SYSTEM'] = 'mac';
1458 } elseif (strstr($useragent,'Linux') || strstr($useragent,'X11') || strstr($useragent,'SGI') || strstr($useragent,' SunOS ') || strstr($useragent,' HP-UX ')) {
1459 $bInfo['SYSTEM'] = 'unix';
1460 }
1461 }
1462
1463 // Is true if the browser supports css to format forms, especially the width
1464 $bInfo['FORMSTYLE']=($bInfo['BROWSER']=='msie' || ($bInfo['BROWSER']=='net'&&$bInfo['VERSION']>=5) || $bInfo['BROWSER']=='opera' || $bInfo['BROWSER']=='konqu');
1465 return $bInfo;
1466 }
1467
1468 /***************************
1469 *
1470 * OTHER FUNCTIONS: (from Classic RTE)
1471 *
1472 ***************************/
1473 /**
1474 * @return [type] ...
1475 * @desc
1476 */
1477
1478 function RTEtsConfigParams() {
1479 if($this->is_FE()) {
1480 return '';
1481 } else {
1482 $p = t3lib_BEfunc::getSpecConfParametersFromArray($this->specConf['rte_transform']['parameters']);
1483 return $this->elementParts[0].':'.$this->elementParts[1].':'.$this->elementParts[2].':'.$this->thePid.':'.$this->typeVal.':'.$this->tscPID.':'.$p['imgpath'];
1484 }
1485 }
1486
1487 public function cleanList($str) {
1488 if (strstr($str,'*')) {
1489 $str = '*';
1490 } else {
1491 $str = implode(',',array_unique(t3lib_div::trimExplode(',',$str,1)));
1492 }
1493 return $str;
1494 }
1495
1496 function filterStyleEl($elValue,$matchList) {
1497 $matchParts = t3lib_div::trimExplode(',',$matchList,1);
1498 $styleParts = explode(';',$elValue);
1499 $nStyle=array();
1500 foreach ($styleParts as $k => $p) {
1501 $pp = t3lib_div::trimExplode(':',$p);
1502 if ($pp[0]&&$pp[1]) {
1503 foreach ($matchParts as $el) {
1504 $star=substr($el,-1)=='*';
1505 if (!strcmp($pp[0],$el) || ($star && t3lib_div::isFirstPartOfStr($pp[0],substr($el,0,-1)) )) {
1506 $nStyle[]=$pp[0].':'.$pp[1];
1507 } else unset($styleParts[$k]);
1508 }
1509 } else {
1510 unset($styleParts[$k]);
1511 }
1512 }
1513 return implode('; ',$nStyle);
1514 }
1515
1516 // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
1517 function loremIpsumInsert($params) {
1518 return "
1519 if (typeof(lorem_ipsum) == 'function' && " . $params['element'] . ".tagName.toLowerCase() == 'textarea' ) lorem_ipsum(" . $params['element'] . ", lipsum_temp_strings[lipsum_temp_pointer]);
1520 ";
1521 }
1522 }
1523
1524 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']) {
1525 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
1526 }
1527
1528 ?>