00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00032 require_once(PATH_tslib.'class.tslib_pibase.php');
00033
00034 class tx_rtehtmlarea_pi1 extends tslib_pibase {
00035 var $cObj;
00036 var $prefixId = 'tx_rtehtmlarea_pi1';
00037 var $scriptRelPath = 'pi1/class.tx_rtehtmlarea_pi1.php';
00038 var $extKey = 'rtehtmlarea';
00039 var $conf = array();
00040 var $siteUrl;
00041 var $charset = 'utf-8';
00042 var $parserCharset = 'utf-8';
00043 var $result;
00044 var $text;
00045 var $misspelled = array();
00046 var $suggestedWords;
00047 var $wordCount = 0;
00048 var $suggestionCount = 0;
00049 var $suggestedWordCount = 0;
00050 var $pspell_link;
00051 var $pspellMode = 'normal';
00052 var $dictionary;
00053 var $AspellDirectory;
00054 var $pspell_is_available;
00055 var $forceCommandMode = 0;
00056 var $filePrefix = 'rtehtmlarea_';
00057 var $uploadFolder = 'uploads/tx_rtehtmlarea/';
00058 var $userUid;
00059 var $personalDictsArg = '';
00060
00068 function main($conf) {
00069 global $TYPO3_CONF_VARS, $TYPO3_DB;
00070
00071 $this->conf = $conf;
00072 $this->tslib_pibase();
00073 $this->pi_setPiVarDefaults();
00074 $this->pi_loadLL();
00075 $this->pi_USER_INT_obj = 1;
00076
00077 $time_start = microtime(true);
00078 $this->pspell_is_available = in_array('pspell', get_loaded_extensions());
00079 $this->AspellDirectory = trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['AspellDirectory'])? trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['AspellDirectory']) : '/usr/bin/aspell';
00080 $this->forceCommandMode = (trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['forceCommandMode']))? trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['forceCommandMode']) : 0;
00081 $safe_mode_is_enabled = ini_get('safe_mode');
00082 if($safe_mode_is_enabled && !$this->pspell_is_available ) echo('Configuration problem: Spell checking cannot be performed');
00083 if($safe_mode_is_enabled && $this->forceCommandMode) echo('Configuration problem: Spell checking cannot be performed in command mode');
00084 if(!$safe_mode_is_enabled && (!$this->pspell_is_available || $this->forceCommandMode)) {
00085 $AspellVersionString = explode('Aspell', shell_exec( $this->AspellDirectory.' -v'));
00086 $AspellVersion = substr( $AspellVersionString[1], 0, 4);
00087 if( doubleval($AspellVersion) < doubleval('0.5') && (!$this->pspell_is_available || $this->forceCommandMode)) echo('Configuration problem: Aspell version ' . $AspellVersion . ' too old. Spell checking cannot be performed in command mode');
00088 }
00089
00090
00091 if(!$safe_mode_is_enabled && (!$this->pspell_is_available || $this->forceCommandMode)) {
00092 $dictionaryList = shell_exec( $this->AspellDirectory.' dump dicts');
00093 $dictionaryList = implode(',', t3lib_div::trimExplode(chr(10), $dictionaryList, 1));
00094 }
00095 if( empty($dictionaryList) ) {
00096 $dictionaryList = trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['dictionaryList']);
00097 }
00098 if( empty($dictionaryList) ) {
00099 $dictionaryList = 'en';
00100 }
00101 $dictionaryArray = t3lib_div::trimExplode(',', $dictionaryList, 1);
00102
00103 $defaultDictionary = trim($TYPO3_CONF_VARS['EXTCONF'][$this->extKey]['defaultDictionary']);
00104 if(!$defaultDictionary || !in_array($defaultDictionary, $dictionaryArray)) {
00105 $defaultDictionary = 'en';
00106 }
00107
00108
00109 $languageArray = array();
00110 $tableA = 'sys_language';
00111 $tableB = 'static_languages';
00112 $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2';
00113 $table = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
00114 $whereClause = '1=1 ';
00115 $whereClause .= ' AND ' . $tableA . '.hidden != 1';
00116 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $table, $whereClause);
00117 while($row = $TYPO3_DB->sql_fetch_assoc($res)) {
00118 $languageArray[] = strtolower($row['lg_iso_2']).($row['lg_country_iso_2']?'_'.$row['lg_country_iso_2']:'');
00119 }
00120 if(!in_array($defaultDictionary, $languageArray)) {
00121 $languageArray[] = $defaultDictionary;
00122 }
00123 foreach ($dictionaryArray as $key => $dict) {
00124 $lang = explode('-', $dict);
00125 if( !in_array(substr($dict, 0, 2), $languageArray) || !empty($lang[1])) {
00126 unset($dictionaryArray[$key]);
00127 } else {
00128 $dictionaryArray[$key] = $lang[0];
00129 }
00130 }
00131 uasort($dictionaryArray, 'strcoll');
00132 $dictionaryList = implode(',', $dictionaryArray);
00133
00134
00135 $this->dictionary = t3lib_div::_POST('dictionary');
00136 if( empty($this->dictionary) || !in_array($this->dictionary, $dictionaryArray)) {
00137 $this->dictionary = $defaultDictionary;
00138 }
00139 $dictionaries = substr_replace($dictionaryList, '@'.$this->dictionary, strpos($dictionaryList, $this->dictionary), strlen($this->dictionary));
00140
00141
00142
00143
00144 $this->pspellMode = t3lib_div::_POST('pspell_mode')?t3lib_div::_POST('pspell_mode'): $this->pspellMode;
00145
00146 $this->pspellMode = t3lib_div::inList('ultra,fast,normal,bad-spellers',$this->pspellMode)?$this->pspellMode:'normal';
00147 switch($this->pspellMode) {
00148 case 'ultra':
00149 case 'fast':
00150 $pspellModeFlag = PSPELL_FAST;
00151 break;
00152 case 'bad-spellers':
00153 $pspellModeFlag = PSPELL_BAD_SPELLERS;
00154 break;
00155 case 'normal':
00156 default:
00157 $pspellModeFlag = PSPELL_NORMAL;
00158 break;
00159 }
00160
00161
00162 if( t3lib_div::_POST('pspell_charset') ) $this->charset = trim(t3lib_div::_POST('pspell_charset'));
00163 if(strtolower($this->charset) == 'iso-8859-1') $this->parserCharset = strtolower($this->charset);
00164 $internal_encoding = mb_internal_encoding(strtoupper($this->parserCharset));
00165
00166
00167 if($this->pspell_is_available && !$this->forceCommandMode) {
00168 $this->pspell_link = pspell_new($this->dictionary, '', '', $this->parserCharset, $pspellModeFlag);
00169 }
00170
00171
00172 if (t3lib_div::_POST('enablePersonalDicts') == 'true' && $GLOBALS['TSFE']->beUserLogin) {
00173 $this->userUid = 'BE_' . $GLOBALS['BE_USER']->user['uid'];
00174 if ($this->userUid) {
00175 $this->personalDictPath = t3lib_div::getFileAbsFileName($this->uploadFolder . $this->userUid);
00176 if (!is_dir($this->personalDictPath)) {
00177 t3lib_div::mkdir($this->personalDictPath);
00178 }
00179
00180 $this->personalDictsArg = ' --home-dir=' . escapeshellarg($this->personalDictPath);
00181 }
00182 }
00183
00184 $cmd = t3lib_div::_POST('cmd');
00185 if ($cmd == 'learn' && !$safe_mode_is_enabled) {
00186
00187 if(!$GLOBALS['TSFE']->beUserLogin) die('');
00188
00189 $to_p_dict = t3lib_div::_POST('to_p_dict');
00190 $to_p_dict = $to_p_dict ? $to_p_dict : array();
00191 $to_r_list = t3lib_div::_POST('to_r_list');
00192 $to_r_list = $to_r_list ? $to_r_list : array();
00193 header('Content-Type: text/plain; charset=' . strtoupper($this->parserCharset));
00194 header('Pragma: no-cache');
00195
00196 if($to_p_dict || $to_r_list) {
00197 $tmpFileName = t3lib_div::tempnam($this->filePrefix);
00198 if($filehandle = fopen($tmpFileName,'wb')) {
00199 foreach ($to_p_dict as $personal_word) {
00200 $cmd = '&' . $personal_word . "\n";
00201 echo $cmd;
00202 fwrite($filehandle, $cmd, strlen($cmd));
00203 }
00204 foreach ($to_r_list as $replace_pair) {
00205 $cmd = '$$ra ' . $replace_pair[0] . ' , ' . $replace_pair[1] . "\n";
00206 echo $cmd;
00207 fwrite($filehandle, $cmd, strlen($cmd));
00208 }
00209 $cmd = "#\n";
00210 echo $cmd;
00211 fwrite($filehandle, $cmd, strlen($cmd));
00212 fclose($filehandle);
00213
00214 $AspellCommand = 'cat ' . escapeshellarg($tmpFileName) . ' | ' . $this->AspellDirectory . ' -a --mode=none' . $this->personalDictsArg . ' --lang=' . escapeshellarg($this->dictionary) . ' --encoding=' . escapeshellarg($this->parserCharset) . ' 2>&1';
00215 print $AspellCommand . "\n";
00216 print shell_exec($AspellCommand);
00217 t3lib_div::unlink_tempfile($tmpFileName);
00218 echo('Personal word list was updated.');
00219 } else {
00220 echo('SpellChecker tempfile open error.');
00221 }
00222 } else {
00223 echo('Nothing to add to the personal word list.');
00224 }
00225 flush();
00226 exit();
00227 } else {
00228
00229
00230 $this->result = '<?xml version="1.0" encoding="' . $this->parserCharset . '"?>
00231 <!DOCTYPE html
00232 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
00233 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
00234 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . substr($this->dictionary, 0, 2) . '" lang="' . substr($this->dictionary, 0, 2) . '">
00235 <html>
00236 <head>
00237 <meta http-equiv="Content-Type" content="text/html; charset=' . $this->parserCharset . '" />
00238 <link rel="stylesheet" type="text/css" media="all" href="spell-check-style.css" />
00239 <script type="text/javascript">
00240
00241 <!--
00242 ';
00243
00244
00245 $content = t3lib_div::_POST('content');
00246
00247
00248 $parser = xml_parser_create(strtoupper($this->parserCharset));
00249 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00250 xml_set_object($parser, &$this);
00251 if( !xml_set_element_handler( $parser, 'startHandler', 'endHandler')) echo('Bad xml handler setting');
00252 if( !xml_set_character_data_handler ( $parser, 'spellCheckHandler')) echo('Bad xml handler setting');
00253 if( !xml_set_default_handler( $parser, 'defaultHandler')) echo('Bad xml handler setting');
00254 if(! xml_parse($parser,'<?xml version="1.0" encoding="' . $this->parserCharset . '"?><spellchecker> ' . mb_ereg_replace(' ', ' ', $content) . ' </spellchecker>')) echo('Bad parsing');
00255 if( xml_get_error_code($parser)) {
00256 die('Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser)));
00257 }
00258 xml_parser_free($parser);
00259 if($this->pspell_is_available && !$this->forceCommandMode) {
00260 pspell_clear_session ($this->pspell_link);
00261 }
00262 $this->result .= 'var suggested_words = {' . $this->suggestedWords . '};
00263 ';
00264
00265
00266 $time = number_format(microtime(true) - $time_start, 2, ',', ' ');
00267
00268
00269 $this->result .= 'var spellcheck_info = { "Total words":"'.$this->wordCount.'","Misspelled words":"'.sizeof($this->misspelled).'","Total suggestions":"'.$this->suggestionCount.'","Total words suggested":"'.$this->suggestedWordCount.'","Spelling checked in":"'.$time.'" };
00270
00271
00272 </script>
00273 </head>
00274 ';
00275 $this->result .= '<body onload="window.parent.finishedSpellChecking();">';
00276 $this->result .= preg_replace('/'.preg_quote('<?xml').'.*'.preg_quote('?>').'['.preg_quote(chr(10).chr(13).chr(32)).']*/', '', $this->text);
00277 $this->result .= '<div id="HA-spellcheck-dictionaries">'.$dictionaries.'</div>';
00278
00279
00280 $this->result .= '
00281 </body></html>';
00282
00283
00284 echo $this->result;
00285 }
00286
00287 }
00288
00289 function startHandler($xml_parser, $tag, $attributes) {
00290 switch($tag) {
00291 case 'spellchecker':
00292 break;
00293 case 'br':
00294 case 'BR':
00295 case 'img':
00296 case 'IMG':
00297 case 'hr':
00298 case 'HR':
00299 case 'area':
00300 case 'AREA':
00301 $this->text .= '<'. mb_strtolower($tag) . ' ';
00302 foreach( $attributes as $key => $val) {
00303 $this->text .= $key . '="' . $val . '" ';
00304 }
00305 $this->text .= ' />';
00306 break;
00307 default:
00308 $this->text .= '<'. mb_strtolower($tag) . ' ';
00309 foreach( $attributes as $key => $val) {
00310 $this->text .= $key . '="' . $val . '" ';
00311 }
00312 $this->text .= '>';
00313 break;
00314 }
00315 return;
00316 }
00317
00318 function endHandler($xml_parser, $tag) {
00319 switch($tag) {
00320 case 'spellchecker':
00321 break;
00322 case 'br':
00323 case 'BR':
00324 case 'img':
00325 case 'IMG':
00326 case 'hr':
00327 case 'HR':
00328 case 'input':
00329 case 'INPUT':
00330 case 'area':
00331 case 'AREA':
00332 break;
00333 default:
00334 $this->text .= '</' . $tag . '>';
00335 break;
00336 }
00337 return;
00338 }
00339
00340 function spellCheckHandler($xml_parser, $string) {
00341 $incurrent=array();
00342 $stringText = $string;
00343 $words = mb_split('\W+', $stringText);
00344 while( list(,$word) = each($words) ) {
00345 $word = mb_ereg_replace(' ', '', $word);
00346 if( $word && !is_numeric($word)) {
00347 if($this->pspell_is_available && !$this->forceCommandMode) {
00348 if (!pspell_check($this->pspell_link, $word)) {
00349 if(!in_array($word, $this->misspelled)) {
00350 if(sizeof($this->misspelled) != 0 ) {
00351 $this->suggestedWords .= ',';
00352 }
00353 $suggest = array();
00354 $suggest = pspell_suggest($this->pspell_link, $word);
00355 if(sizeof($suggest) != 0 ) {
00356 $this->suggestionCount++;
00357 $this->suggestedWordCount += sizeof($suggest);
00358 }
00359 $this->suggestedWords .= '"'.$word.'":"'.implode(',',$suggest).'"';
00360 $this->misspelled[] = $word;
00361 unset($suggest);
00362 }
00363 if( !in_array($word, $incurrent) ) {
00364 $stringText = mb_ereg_replace('\b'.$word.'\b', '<span class="HA-spellcheck-error">'.$word.'</span>', $stringText);
00365 $incurrent[] = $word;
00366 }
00367 }
00368 } else {
00369 $tmpFileName = t3lib_div::tempnam($this->filePrefix);
00370 if(!$filehandle = fopen($tmpFileName,'wb')) echo('SpellChecker tempfile open error');
00371 if(!fwrite($filehandle, $word)) echo('SpellChecker tempfile write error');
00372 if(!fclose($filehandle)) echo('SpellChecker tempfile close error');
00373 $AspellCommand = 'cat ' . escapeshellarg($tmpFileName) . ' | ' . $this->AspellDirectory . ' -a check --mode=none --sug-mode=' . escapeshellarg($this->pspellMode) . $this->personalDictsArg . ' --lang=' . escapeshellarg($this->dictionary) . ' --encoding=' . escapeshellarg($this->parserCharset) . ' 2>&1';
00374 $AspellAnswer = shell_exec($AspellCommand);
00375 $AspellResultLines = array();
00376 $AspellResultLines = t3lib_div::trimExplode(chr(10), $AspellAnswer, 1);
00377 if(substr($AspellResultLines[0],0,6) == 'Error:') echo("{$AspellAnswer}");
00378 t3lib_div::unlink_tempfile($tmpFileName);
00379 if(substr($AspellResultLines['1'],0,1) != '*') {
00380 if(!in_array($word, $this->misspelled)) {
00381 if(sizeof($this->misspelled) != 0 ) {
00382 $this->suggestedWords .= ',';
00383 }
00384 $suggest = array();
00385 $suggestions = array();
00386 if (substr($AspellResultLines['1'],0,1) == '&') {
00387 $suggestions = t3lib_div::trimExplode(':', $AspellResultLines['1'], 1);
00388 $suggest = t3lib_div::trimExplode(',', $suggestions['1'], 1);
00389 }
00390 if (sizeof($suggest) != 0) {
00391 $this->suggestionCount++;
00392 $this->suggestedWordCount += sizeof($suggest);
00393 }
00394 $this->suggestedWords .= '"'.$word.'":"'.implode(',',$suggest).'"';
00395 $this->misspelled[] = $word;
00396 unset($suggest);
00397 unset($suggestions);
00398 }
00399 if (!in_array($word, $incurrent)) {
00400 $stringText = mb_ereg_replace('\b'.$word.'\b', '<span class="HA-spellcheck-error">'.$word.'</span>', $stringText);
00401 $incurrent[] = $word;
00402 }
00403 }
00404 unset($AspellResultLines);
00405 }
00406 $this->wordCount++;
00407 }
00408 }
00409 $this->text .= $stringText;
00410 unset($incurrent);
00411 return;
00412 }
00413
00414 function defaultHandler($xml_parser, $string) {
00415 $this->text .= $string;
00416 return;
00417 }
00418
00419 }
00420
00421 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/pi1/class.tx_rtehtmlarea_pi1.php']) {
00422 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/pi1/class.tx_rtehtmlarea_pi1.php']);
00423 }
00424
00425 ?>