ed52984e1ce9a166ce1dbe331e6992210266e4fb
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Controller / SpellCheckingController.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2003-2012 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 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * Spell checking plugin 'tx_rtehtmlarea_pi1' for the htmlArea RTE extension.
28 *
29 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
30 */
31 class SpellCheckingController {
32
33 // Instance of t3lib_cs
34 protected $csConvObj;
35
36 // The extension key
37 /**
38 * @todo Define visibility
39 */
40 public $extKey = 'rtehtmlarea';
41
42 /**
43 * @todo Define visibility
44 */
45 public $siteUrl;
46
47 /**
48 * @todo Define visibility
49 */
50 public $charset = 'utf-8';
51
52 /**
53 * @todo Define visibility
54 */
55 public $parserCharset = 'utf-8';
56
57 /**
58 * @todo Define visibility
59 */
60 public $defaultAspellEncoding = 'utf-8';
61
62 /**
63 * @todo Define visibility
64 */
65 public $aspellEncoding;
66
67 /**
68 * @todo Define visibility
69 */
70 public $result;
71
72 /**
73 * @todo Define visibility
74 */
75 public $text;
76
77 /**
78 * @todo Define visibility
79 */
80 public $misspelled = array();
81
82 /**
83 * @todo Define visibility
84 */
85 public $suggestedWords;
86
87 /**
88 * @todo Define visibility
89 */
90 public $wordCount = 0;
91
92 /**
93 * @todo Define visibility
94 */
95 public $suggestionCount = 0;
96
97 /**
98 * @todo Define visibility
99 */
100 public $suggestedWordCount = 0;
101
102 /**
103 * @todo Define visibility
104 */
105 public $pspell_link;
106
107 /**
108 * @todo Define visibility
109 */
110 public $pspellMode = 'normal';
111
112 /**
113 * @todo Define visibility
114 */
115 public $dictionary;
116
117 /**
118 * @todo Define visibility
119 */
120 public $AspellDirectory;
121
122 /**
123 * @todo Define visibility
124 */
125 public $pspell_is_available;
126
127 /**
128 * @todo Define visibility
129 */
130 public $forceCommandMode = 0;
131
132 /**
133 * @todo Define visibility
134 */
135 public $filePrefix = 'rtehtmlarea_';
136
137 // Pre-FAL backward compatibility
138 protected $uploadFolder = 'uploads/tx_rtehtmlarea/';
139
140 // Path to main dictionary
141 protected $mainDictionaryPath;
142
143 // Path to personal dictionary
144 protected $personalDictionaryPath;
145
146 /**
147 * @todo Define visibility
148 */
149 public $xmlCharacterData = '';
150
151 /**
152 * Main class of Spell Checker plugin for Typo3 CMS
153 *
154 * @return string content produced by the plugin
155 * @todo Define visibility
156 */
157 public function main() {
158 $this->csConvObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
159 // Setting start time
160 $time_start = microtime(TRUE);
161 $this->pspell_is_available = in_array('pspell', get_loaded_extensions());
162 $this->AspellDirectory = trim($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['plugins']['SpellChecker']['AspellDirectory']) ? trim($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['plugins']['SpellChecker']['AspellDirectory']) : '/usr/bin/aspell';
163 // Setting command mode if requested and available
164 $this->forceCommandMode = trim($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['plugins']['SpellChecker']['forceCommandMode']) ? trim($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['plugins']['SpellChecker']['forceCommandMode']) : 0;
165 if (!$this->pspell_is_available || $this->forceCommandMode) {
166 $AspellVersionString = explode('Aspell', shell_exec($this->AspellDirectory . ' -v'));
167 $AspellVersion = substr($AspellVersionString[1], 0, 4);
168 if (doubleval($AspellVersion) < doubleval('0.5') && (!$this->pspell_is_available || $this->forceCommandMode)) {
169 echo 'Configuration problem: Aspell version ' . $AspellVersion . ' too old. Spell checking cannot be performed in command mode.';
170 }
171 $this->defaultAspellEncoding = trim(shell_exec($this->AspellDirectory . ' config encoding'));
172 }
173 // Setting the list of dictionaries
174 $dictionaryList = shell_exec($this->AspellDirectory . ' dump dicts');
175 $dictionaryList = implode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, $dictionaryList, 1));
176 $dictionaryArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $dictionaryList, 1);
177 $restrictToDictionaries = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('restrictToDictionaries');
178 if ($restrictToDictionaries) {
179 $dictionaryArray = array_intersect($dictionaryArray, \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $restrictToDictionaries, 1));
180 }
181 if (!count($dictionaryArray)) {
182 $dictionaryArray[] = 'en';
183 }
184 $this->dictionary = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('dictionary');
185 $defaultDictionary = $this->dictionary;
186 if (!$defaultDictionary || !in_array($defaultDictionary, $dictionaryArray)) {
187 $defaultDictionary = 'en';
188 }
189 uasort($dictionaryArray, 'strcoll');
190 $dictionaryList = implode(',', $dictionaryArray);
191 // Setting the dictionary
192 if (empty($this->dictionary) || !in_array($this->dictionary, $dictionaryArray)) {
193 $this->dictionary = 'en';
194 }
195 // Setting the pspell suggestion mode
196 $this->pspellMode = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('pspell_mode') ? \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('pspell_mode') : $this->pspellMode;
197 // Now sanitize $this->pspellMode
198 $this->pspellMode = \TYPO3\CMS\Core\Utility\GeneralUtility::inList('ultra,fast,normal,bad-spellers', $this->pspellMode) ? $this->pspellMode : 'normal';
199 switch ($this->pspellMode) {
200 case 'ultra':
201
202 case 'fast':
203 $pspellModeFlag = PSPELL_FAST;
204 break;
205 case 'bad-spellers':
206 $pspellModeFlag = PSPELL_BAD_SPELLERS;
207 break;
208 case 'normal':
209
210 default:
211 $pspellModeFlag = PSPELL_NORMAL;
212 break;
213 }
214 // Setting the charset
215 if (\TYPO3\CMS\Core\Utility\GeneralUtility::_POST('pspell_charset')) {
216 $this->charset = trim(\TYPO3\CMS\Core\Utility\GeneralUtility::_POST('pspell_charset'));
217 }
218 if (strtolower($this->charset) == 'iso-8859-1') {
219 $this->parserCharset = strtolower($this->charset);
220 }
221 // In some configurations, Aspell uses 'iso8859-1' instead of 'iso-8859-1'
222 $this->aspellEncoding = $this->parserCharset;
223 if ($this->parserCharset == 'iso-8859-1' && strstr($this->defaultAspellEncoding, '8859-1')) {
224 $this->aspellEncoding = $this->defaultAspellEncoding;
225 }
226 // However, we are going to work only in the parser charset
227 if ($this->pspell_is_available && !$this->forceCommandMode) {
228 $this->pspell_link = pspell_new($this->dictionary, '', '', $this->parserCharset, $pspellModeFlag);
229 }
230 // Setting the path to main dictionary
231 $this->setMainDictionaryPath();
232 // Setting the path to user personal dictionary, if any
233 $this->setPersonalDictionaryPath();
234 $this->fixPersonalDictionaryCharacterSet();
235 $cmd = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('cmd');
236 if ($cmd == 'learn') {
237 // Only availble for BE_USERS, die silently if someone has gotten here by accident
238 if (TYPO3_MODE !== 'BE' || !is_object($GLOBALS['BE_USER'])) {
239 die('');
240 }
241 // Updating the personal word list
242 $to_p_dict = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('to_p_dict');
243 $to_p_dict = $to_p_dict ? $to_p_dict : array();
244 $to_r_list = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('to_r_list');
245 $to_r_list = $to_r_list ? $to_r_list : array();
246 header('Content-Type: text/plain; charset=' . strtoupper($this->parserCharset));
247 header('Pragma: no-cache');
248 if ($to_p_dict || $to_r_list) {
249 $tmpFileName = \TYPO3\CMS\Core\Utility\GeneralUtility::tempnam($this->filePrefix);
250 $filehandle = fopen($tmpFileName, 'wb');
251 if ($filehandle) {
252 // Get the character set of the main dictionary
253 // We need to convert the input into the character set of the main dictionary
254 $mainDictionaryCharacterSet = $this->getMainDictionaryCharacterSet();
255 // Write the personal words addition commands to the temporary file
256 foreach ($to_p_dict as $personal_word) {
257 $cmd = '&' . $this->csConvObj->conv($personal_word, $this->parserCharset, $mainDictionaryCharacterSet) . LF;
258 fwrite($filehandle, $cmd, strlen($cmd));
259 }
260 // Write the replacent pairs addition commands to the temporary file
261 foreach ($to_r_list as $replace_pair) {
262 $cmd = '$$ra ' . $this->csConvObj->conv($replace_pair[0], $this->parserCharset, $mainDictionaryCharacterSet) . ' , ' . $this->csConvObj->conv($replace_pair[1], $this->parserCharset, $mainDictionaryCharacterSet) . LF;
263 fwrite($filehandle, $cmd, strlen($cmd));
264 }
265 $cmd = '#' . LF;
266 fwrite($filehandle, $cmd, strlen($cmd));
267 // Assemble the Aspell command
268 $AspellCommand = (TYPO3_OS === 'WIN' ? 'type ' : 'cat ') . escapeshellarg($tmpFileName) . ' | ' . $this->AspellDirectory . ' -a --mode=none' . ($this->personalDictionaryPath ? ' --home-dir=' . escapeshellarg($this->personalDictionaryPath) : '') . ' --lang=' . escapeshellarg($this->dictionary) . ' --encoding=' . escapeshellarg($mainDictionaryCharacterSet) . ' 2>&1';
269 $AspellAnswer = shell_exec($AspellCommand);
270 // Close and delete the temporary file
271 fclose($filehandle);
272 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($tmpFileName);
273 echo 'Personal word list was updated.';
274 } else {
275 \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('SpellChecker tempfile open error: ' . $tmpFileName, $this->extKey, \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
276 echo 'SpellChecker tempfile open error.';
277 }
278 } else {
279 echo 'Nothing to add to the personal word list.';
280 }
281 flush();
282 die;
283 } else {
284 // Check spelling content
285 // Initialize output
286 $this->result = '<?xml version="1.0" encoding="' . $this->parserCharset . '"?>
287 <!DOCTYPE html
288 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
289 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
290 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . substr($this->dictionary, 0, 2) . '" lang="' . substr($this->dictionary, 0, 2) . '">
291 <head>
292 <meta http-equiv="Content-Type" content="text/html; charset=' . $this->parserCharset . '" />
293 <link rel="stylesheet" type="text/css" media="all" href="' . (TYPO3_MODE == 'BE' ? '../' : '') . \TYPO3\CMS\Core\Extension\ExtensionManager::siteRelPath($this->extKey) . '/htmlarea/plugins/SpellChecker/spell-check-style.css" />
294 <script type="text/javascript">
295 /*<![CDATA[*/
296 <!--
297 ';
298 // Getting the input content
299 $content = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('content');
300 // Parsing the input HTML
301 $parser = xml_parser_create(strtoupper($this->parserCharset));
302 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
303 xml_set_object($parser, $this);
304 if (!xml_set_element_handler($parser, 'startHandler', 'endHandler')) {
305 echo 'Bad xml handler setting';
306 }
307 if (!xml_set_character_data_handler($parser, 'collectDataHandler')) {
308 echo 'Bad xml handler setting';
309 }
310 if (!xml_set_default_handler($parser, 'defaultHandler')) {
311 echo 'Bad xml handler setting';
312 }
313 if (!xml_parse($parser, ('<?xml version="1.0" encoding="' . $this->parserCharset . '"?><spellchecker> ' . preg_replace(('/&nbsp;/' . ($this->parserCharset == 'utf-8' ? 'u' : '')), ' ', $content) . ' </spellchecker>'))) {
314 echo 'Bad parsing';
315 }
316 if (xml_get_error_code($parser)) {
317 throw new \UnexpectedException('Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser)), 1294585788);
318 }
319 xml_parser_free($parser);
320 if ($this->pspell_is_available && !$this->forceCommandMode) {
321 pspell_clear_session($this->pspell_link);
322 }
323 $this->result .= 'var suggestedWords = {' . $this->suggestedWords . '};
324 var dictionaries = "' . $dictionaryList . '";
325 var selectedDictionary = "' . $this->dictionary . '";
326 ';
327 // Calculating parsing and spell checkting time
328 $time = number_format(microtime(TRUE) - $time_start, 2, ',', ' ');
329 // Insert spellcheck info
330 $this->result .= 'var spellcheckInfo = { "Total words":"' . $this->wordCount . '","Misspelled words":"' . sizeof($this->misspelled) . '","Total suggestions":"' . $this->suggestionCount . '","Total words suggested":"' . $this->suggestedWordCount . '","Spelling checked in":"' . $time . '" };
331 // -->
332 /*]]>*/
333 </script>
334 </head>
335 ';
336 $this->result .= '<body onload="window.parent.RTEarea[\'' . \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('editorId') . '\'].editor.getPlugin(\'SpellChecker\').spellCheckComplete();">';
337 $this->result .= preg_replace('/' . preg_quote('<?xml') . '.*' . preg_quote('?>') . '[' . preg_quote((LF . CR . chr(32))) . ']*/' . ($this->parserCharset == 'utf-8' ? 'u' : ''), '', $this->text);
338 $this->result .= '<div style="display: none;">' . $dictionaries . '</div>';
339 // Closing
340 $this->result .= '
341 </body></html>';
342 // Outputting
343 header('Content-Type: text/html; charset=' . strtoupper($this->parserCharset));
344 echo $this->result;
345 }
346 }
347
348 /**
349 * Sets the path to the main dictionary
350 *
351 * @return string path to the main dictionary
352 */
353 protected function setMainDictionaryPath() {
354 $this->mainDictionaryPath = trim(shell_exec($this->AspellDirectory . ' config dict-dir'));
355 return $this->mainDictionaryPath;
356 }
357
358 /**
359 * Gets the character set the main dictionary
360 *
361 * @return string character set the main dictionary
362 */
363 protected function getMainDictionaryCharacterSet() {
364 $characterSet = '';
365 // Read the options of the dictionary
366 $dictionaryHandle = fopen($this->mainDictionaryPath . '/' . $this->dictionary . '.dat', 'rb');
367 $dictionaryContent = fread($dictionaryHandle, 500);
368 fclose($dictionaryHandle);
369 // Get the line that contains the character set option
370 $dictionaryContent = preg_split('/charset\\s*/', $dictionaryContent, 2);
371 if ($dictionaryContent[1]) {
372 // Isolate the character set
373 $dictionaryContent = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, $dictionaryContent[1]);
374 $characterSet = $dictionaryContent[0];
375 }
376 // Fix Aspell character set oddity (i.e. iso8859-1)
377 $characterSet = str_replace('iso', 'iso-', $characterSet);
378 $characterSet = str_replace('--', '-', $characterSet);
379 return $characterSet;
380 }
381
382 /**
383 * Sets the path to the personal dictionary
384 *
385 * @return string path to the personal dictionary
386 */
387 protected function setPersonalDictionaryPath() {
388 $this->personalDictionaryPath = '';
389 if (\TYPO3\CMS\Core\Utility\GeneralUtility::_POST('enablePersonalDicts') == 'true' && TYPO3_MODE == 'BE' && is_object($GLOBALS['BE_USER'])) {
390 if ($GLOBALS['BE_USER']->user['uid']) {
391 $personalDictionaryFolderName = 'BE_' . $GLOBALS['BE_USER']->user['uid'];
392 // Check for pre-FAL personal dictionary folder
393 try {
394 $personalDictionaryFolder = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier(PATH_site . $this->uploadFolder . $personalDictionaryFolderName);
395 } catch (\Exception $e) {
396 $personalDictionaryFolder = FALSE;
397 }
398 // The personal dictionary folder is created in the user's default upload folder and named BE_(uid)_personaldictionary
399 if (!$personalDictionaryFolder) {
400 $personalDictionaryFolderName .= '_personaldictionary';
401 $backendUserDefaultFolder = $GLOBALS['BE_USER']->getDefaultUploadFolder();
402 if ($backendUserDefaultFolder->hasFolder($personalDictionaryFolderName)) {
403 $personalDictionaryFolder = $backendUserDefaultFolder->getSubfolder($personalDictionaryFolderName);
404 } else {
405 $personalDictionaryFolder = $backendUserDefaultFolder->createFolder($personalDictionaryFolderName);
406 }
407 }
408 $this->personalDictionaryPath = PATH_site . rtrim($personalDictionaryFolder->getPublicUrl(), '/');
409 }
410 }
411 return $this->personalDictionaryPath;
412 }
413
414 /**
415 * Ensures that the personal dictionary is utf-8 encoded
416 *
417 * @return void
418 */
419 protected function fixPersonalDictionaryCharacterSet() {
420 // Fix the options of the personl word list and of the replacement pairs files
421 $fileNames = array();
422 $fileNames[0] = $this->personalDictionaryPath . '/' . '.aspell.' . $this->dictionary . '.pws';
423 $fileNames[1] = $this->personalDictionaryPath . '/' . '.aspell.' . $this->dictionary . '.prepl';
424 foreach ($fileNames as $fileName) {
425 if (file_exists($fileName)) {
426 $fileContent = file_get_contents($fileName);
427 $fileContent = explode(LF, $fileContent);
428 if (strpos($fileContent[0], 'utf-8') === FALSE) {
429 $fileContent[0] .= ' utf-8';
430 }
431 $fileContent = implode(LF, $fileContent);
432 file_put_contents($fileName, $fileContent);
433 }
434 }
435 }
436
437 /**
438 * @todo Define visibility
439 */
440 public function startHandler($xml_parser, $tag, $attributes) {
441 if (strlen($this->xmlCharacterData)) {
442 $this->spellCheckHandler($xml_parser, $this->xmlCharacterData);
443 $this->xmlCharacterData = '';
444 }
445 switch ($tag) {
446 case 'spellchecker':
447 break;
448 case 'br':
449
450 case 'BR':
451
452 case 'img':
453
454 case 'IMG':
455
456 case 'hr':
457
458 case 'HR':
459
460 case 'area':
461
462 case 'AREA':
463 $this->text .= '<' . $this->csConvObj->conv_case($this->parserCharset, $tag, 'toLower') . ' ';
464 foreach ($attributes as $key => $val) {
465 $this->text .= $key . '="' . $val . '" ';
466 }
467 $this->text .= ' />';
468 break;
469 default:
470 $this->text .= '<' . $this->csConvObj->conv_case($this->parserCharset, $tag, 'toLower') . ' ';
471 foreach ($attributes as $key => $val) {
472 $this->text .= $key . '="' . $val . '" ';
473 }
474 $this->text .= '>';
475 break;
476 }
477 }
478
479 /**
480 * @todo Define visibility
481 */
482 public function endHandler($xml_parser, $tag) {
483 if (strlen($this->xmlCharacterData)) {
484 $this->spellCheckHandler($xml_parser, $this->xmlCharacterData);
485 $this->xmlCharacterData = '';
486 }
487 switch ($tag) {
488 case 'spellchecker':
489 break;
490 case 'br':
491
492 case 'BR':
493
494 case 'img':
495
496 case 'IMG':
497
498 case 'hr':
499
500 case 'HR':
501
502 case 'input':
503
504 case 'INPUT':
505
506 case 'area':
507
508 case 'AREA':
509 break;
510 default:
511 $this->text .= '</' . $tag . '>';
512 break;
513 }
514 }
515
516 /**
517 * @todo Define visibility
518 */
519 public function spellCheckHandler($xml_parser, $string) {
520 $incurrent = array();
521 $stringText = $string;
522 $words = preg_split($this->parserCharset == 'utf-8' ? '/\\P{L}+/u' : '/\\W+/', $stringText);
523 while (list(, $word) = each($words)) {
524 $word = preg_replace('/ /' . ($this->parserCharset == 'utf-8' ? 'u' : ''), '', $word);
525 if ($word && !is_numeric($word)) {
526 if ($this->pspell_is_available && !$this->forceCommandMode) {
527 if (!pspell_check($this->pspell_link, $word)) {
528 if (!in_array($word, $this->misspelled)) {
529 if (sizeof($this->misspelled) != 0) {
530 $this->suggestedWords .= ',';
531 }
532 $suggest = array();
533 $suggest = pspell_suggest($this->pspell_link, $word);
534 if (sizeof($suggest) != 0) {
535 $this->suggestionCount++;
536 $this->suggestedWordCount += sizeof($suggest);
537 }
538 $this->suggestedWords .= '"' . $word . '":"' . implode(',', $suggest) . '"';
539 $this->misspelled[] = $word;
540 unset($suggest);
541 }
542 if (!in_array($word, $incurrent)) {
543 $stringText = preg_replace('/\\b' . $word . '\\b/' . ($this->parserCharset == 'utf-8' ? 'u' : ''), '<span class="htmlarea-spellcheck-error">' . $word . '</span>', $stringText);
544 $incurrent[] = $word;
545 }
546 }
547 } else {
548 $tmpFileName = \TYPO3\CMS\Core\Utility\GeneralUtility::tempnam($this->filePrefix);
549 if (!($filehandle = fopen($tmpFileName, 'wb'))) {
550 echo 'SpellChecker tempfile open error';
551 }
552 if (!fwrite($filehandle, $word)) {
553 echo 'SpellChecker tempfile write error';
554 }
555 if (!fclose($filehandle)) {
556 echo 'SpellChecker tempfile close error';
557 }
558 $catCommand = TYPO3_OS == 'WIN' ? 'type' : 'cat';
559 $AspellCommand = $catCommand . ' ' . escapeshellarg($tmpFileName) . ' | ' . $this->AspellDirectory . ' -a check --mode=none --sug-mode=' . escapeshellarg($this->pspellMode) . ($this->personalDictionaryPath ? ' --home-dir=' . escapeshellarg($this->personalDictionaryPath) : '') . ' --lang=' . escapeshellarg($this->dictionary) . ' --encoding=' . escapeshellarg($this->aspellEncoding) . ' 2>&1';
560 $AspellAnswer = shell_exec($AspellCommand);
561 $AspellResultLines = array();
562 $AspellResultLines = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, $AspellAnswer, 1);
563 if (substr($AspellResultLines[0], 0, 6) == 'Error:') {
564 echo '{' . $AspellAnswer . '}';
565 }
566 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($tmpFileName);
567 if (substr($AspellResultLines['1'], 0, 1) != '*') {
568 if (!in_array($word, $this->misspelled)) {
569 if (sizeof($this->misspelled) != 0) {
570 $this->suggestedWords .= ',';
571 }
572 $suggest = array();
573 $suggestions = array();
574 if (substr($AspellResultLines['1'], 0, 1) == '&') {
575 $suggestions = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(':', $AspellResultLines['1'], 1);
576 $suggest = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $suggestions['1'], 1);
577 }
578 if (sizeof($suggest) != 0) {
579 $this->suggestionCount++;
580 $this->suggestedWordCount += sizeof($suggest);
581 }
582 $this->suggestedWords .= '"' . $word . '":"' . implode(',', $suggest) . '"';
583 $this->misspelled[] = $word;
584 unset($suggest);
585 unset($suggestions);
586 }
587 if (!in_array($word, $incurrent)) {
588 $stringText = preg_replace('/\\b' . $word . '\\b/' . ($this->parserCharset == 'utf-8' ? 'u' : ''), '<span class="htmlarea-spellcheck-error">' . $word . '</span>', $stringText);
589 $incurrent[] = $word;
590 }
591 }
592 unset($AspellResultLines);
593 }
594 $this->wordCount++;
595 }
596 }
597 $this->text .= $stringText;
598 unset($incurrent);
599 }
600
601 /**
602 * @todo Define visibility
603 */
604 public function collectDataHandler($xml_parser, $string) {
605 $this->xmlCharacterData .= $string;
606 }
607
608 /**
609 * @todo Define visibility
610 */
611 public function defaultHandler($xml_parser, $string) {
612 $this->text .= $string;
613 }
614
615 }
616
617
618 ?>