6 * Squirrelspell module.
8 * This module is the main workhorse of SquirrelSpell. It submits
9 * the message to the spell-checker, parses the output, and loads
10 * the interface window.
12 * @author Konstantin Riabitsev <icon at duke.edu>
13 * @copyright 1999-2016 The SquirrelMail Project Team
14 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
17 * @subpackage squirrelspell
21 * This function makes a javascript-powered link. Not sure why
22 * Philippe decided to move it outside the main code, but hey. ;)
23 * I bet for the i18n reasons.
25 * @param $jscode Javascript code to include in the link.
26 * @param $title A little pop-up title to provide for the links.
27 * @param $link The content of the link.
28 * @return void, since this just draws the content.
30 function SpellLink($jscode, $title, $link) {
31 echo "<td><a href=\"javascript:$jscode\" "
32 . "title=\"$title\">$link</a>"
37 * Declaring globals for users with E_ALL set.
39 global $SQSPELL_APP_DEFAULT, $SQSPELL_APP, $SQSPELL_SPELLCHECKER,
40 $SQSPELL_FORCE_POPEN, $attachment_dir, $color;
42 if (! sqgetGlobalVar('sqspell_text',$sqspell_text,SQ_POST)) {
45 if (! sqgetGlobalVar('sqspell_use_app',$sqspell_use_app,SQ_POST)) {
46 $sqspell_use_app = $SQSPELL_APP_DEFAULT;
50 * Now we explode the lines for two reasons:
51 * 1) So we can ignore lines starting with ">" (reply's)
52 * 2) So we can stop processing when we get to "--" on a single line,
53 * which means that the signature is starting
55 $sqspell_raw_lines = explode("\n", $sqspell_text);
56 for ($i=0; $i<sizeof($sqspell_raw_lines); $i++){
58 * See if the signature is starting, which will be a "--" on the
59 * single line (after trimming).
61 if (trim($sqspell_raw_lines[$i]) == '--'){
65 * See if this is quoted text. Don't check the quoted text, since
66 * it's no business of ours how badly our correspondents misspell
69 if(substr($sqspell_raw_lines[$i], 0, 1) != '>'){
70 $sqspell_new_lines[$i] = $sqspell_raw_lines[$i];
72 $sqspell_new_lines[$i] = '';
76 * $sqspell_new_lines array now contains the lines to submit to the
79 $sqspell_new_text=implode("\n", $sqspell_new_lines);
81 include_once(SM_PATH . 'plugins/squirrelspell/class/common.php');
84 $aParams['words'] = sqspell_getLang($sqspell_use_app);
86 if ($SQSPELL_SPELLCHECKER===1) {
87 include_once(SM_PATH . 'plugins/squirrelspell/class/php_pspell.php');
88 $aParams['dictionary'] = $SQSPELL_APP[$sqspell_use_app];
89 $aParams['charset'] = $default_charset;
90 $check = new php_pspell($aParams);
92 include_once(SM_PATH . 'plugins/squirrelspell/class/cmd_spell.php');
93 $aParams['spell_command'] = $SQSPELL_APP[$sqspell_use_app];
94 if ($SQSPELL_FORCE_POPEN) {
95 $aParams['use_proc_open'] = false;
97 $aParams['use_proc_open'] = check_php_version(4,3);
99 $aParams['temp_dir'] = $attachment_dir;
100 $aParams['debug'] = false;
101 $check = new cmd_spell($aParams);
105 * Check for class constructor function errors
107 if (!empty($check->error)) {
108 $msg= '<div style="text-align: center;">'
109 . nl2br(sm_encode_html_special_chars($check->error))
110 . '<form onsubmit="return false">'
111 . '<input type="submit" value=" ' . _("Close")
112 . ' " onclick="self.close()" /></form></div>';
113 sqspell_makeWindow(null, _("SquirrelSpell is misconfigured."), null, $msg);
117 $missed_words=Array();
119 $locations = Array();
121 $results = $check->check_text($sqspell_new_text);
124 * Check for execution errors
126 if (!empty($check->error)) {
127 $msg= '<div style="text-align: center;">'
128 . nl2br(sm_encode_html_special_chars($check->error))
129 . '<form onsubmit="return false">'
130 . '<input type="submit" value=" ' . _("Close")
131 . ' " onclick="self.close()" /></form></div>';
132 sqspell_makeWindow(null, _("SquirrelSpell is misconfigured."), null, $msg);
136 if (is_array($results)) {
137 // convert variables to old style squirrelspell results
138 if (!empty($results)) {
139 foreach(array_keys($results) as $word) {
140 if (isset($results[$word]['locations'])) {
141 $missed_words[] = $word;
142 $locations[$word] = implode(', ',$results[$word]['locations']);
143 if (isset($results[$word]['suggestions'])) {
144 $misses[$word] = implode(', ',$results[$word]['suggestions']);
146 $misses[$word] = '_NONE';
149 // $word without 'locations'. ignore it
152 $errors = count($missed_words);
155 if (!empty($check->error)) {
156 $error_msg = nl2br(sm_encode_html_special_chars($check->error));
158 $error_msg = _("Unknown error");
160 $msg= '<div style="text-align: center;">'
162 . '<form onsubmit="return false">'
163 . '<input type="submit" value=" ' . _("Close")
164 . ' " onclick="self.close()" /></form></div>';
165 sqspell_makeWindow(null, _("SquirrelSpell error."), null, $msg);
171 * Load the spelling errors into JavaScript arrays
174 $extrajs="<script type=\"text/javascript\">\n"
177 $sqspell_lines = explode("\n", $sqspell_text);
179 * The javascript array sqspell_lines[] contains all lines of
180 * the message we've been checking.
182 $extrajs.= "var sqspell_lines=new Array();\n";
183 for ($i=0; $i<sizeof($sqspell_lines); $i++){
184 // use addcslashes for compatibility with magic_quotes_sybase
185 $extrajs.= "sqspell_lines[$i] = \""
186 . chop(addcslashes($sqspell_lines[$i], ">'\"\\\x0")) . "\";\n";
191 * The javascript array misses[] contais all misspelled words.
193 $extrajs.= "var misses=new Array();\n";
194 for ($i=0; $i<sizeof($missed_words); $i++){
195 $extrajs.= "misses[$i] = \"" . $missed_words[$i] . "\";\n";
200 * Suggestions are (guess what!) suggestions for misspellings
202 $extrajs.= "var suggestions = new Array();\n";
204 while (list($word, $value) = each($misses)){
205 if ($value=='_NONE') $value='';
206 $extrajs.= "suggestions[$i] = \"$value\";\n";
212 * Locations are where those misspellings are located, line:symbol
214 $extrajs.= "var locations= new Array();\n";
216 while (list($word, $value) = each($locations)){
217 $extrajs.= "locations[$i] = \"$value\";\n";
222 * Add some strings so they can be i18n'd.
224 $extrajs.= "var ui_completed = \"" . _("Spellcheck completed. Commit changes?")
226 $extrajs.= "var ui_nochange = \"" . _("No changes were made.") . "\";\n";
227 $extrajs.= "var ui_wait = \""
228 . _("Now saving your personal dictionary... Please wait.")
233 * Did I mention that I hate dots on the end of concatenated lines?
234 * Dots at the beginning make so much more sense!
238 . "<script src=\"js/check_me.js\" type=\"text/javascript\"></script>\n";
241 displayHtmlHeader(_("SquirrelSpell Results"),$extrajs);
243 echo "<body bgcolor=\"$color[4]\" text=\"$color[8]\" link=\"$color[7]\" "
244 . "alink=\"$color[7]\" vlink=\"$color[7]\" "
245 . "onload=\"populateSqspellForm()\">\n";
247 <table width="100%" border="0" cellpadding="2">
249 <td bgcolor="<?php echo $color[9] ?>" align="center">
251 <?php printf( ngettext("Found %d error","Found %d errors",$errors), $errors ) ?>
263 <input type="hidden" name="MOD" value="forget_me_not" />
264 <input type="hidden" name="words" value="" />
265 <input type="hidden" name="sqspell_use_app"
266 value="<?php echo $sqspell_use_app ?>" />
267 <table border="0" width="100%">
271 $sptag = "<span style=\"background-color: $color[9]\">";
272 echo $sptag . _("Line with an error:") . '</span>';
275 <textarea name="sqspell_line_area" cols="50" rows="3"
276 onfocus="this.blur()"></textarea>
280 <td align="right" width="25%">
282 echo $sptag . _("Error:") . '</span>';
285 <td align="left" width="25%">
286 <input name="sqspell_error" size="10" value=""
287 onfocus="this.blur()" />
289 <td align="right" width="25%">
291 echo $sptag . _("Suggestions:") . '</span>';
294 <td align="left" width="25%">
295 <select name="sqspell_suggestion"
296 onchange="if (this.options[this.selectedIndex].value != '_NONE') document.forms[0].sqspell_oruse.value=this.options[this.selectedIndex].value">
298 echo '<option>' . _("Suggestions") . '</option>';
306 echo $sptag . _("Change to:") . '</span>';
310 <input name="sqspell_oruse" size="15" value=""
311 onfocus="if(!this.value) this.value=document.forms[0].sqspell_error.value" />
315 echo $sptag . _("Occurs times:") . '</span>';
319 <input name="sqspell_likethis" size=3 value="" onfocus="this.blur()" />
322 <!-- hello? What is this? </td></tr> -->
324 <td colspan="4"><hr /></td>
328 <table border="0" cellpadding="0" cellspacing="3" width="100%">
329 <tr align="center" bgcolor="<?php echo $color[9] ?>">
331 SpellLink('sqspellChange()',
332 _("Change this word"),
334 SpellLink('sqspellChangeAll()',
335 _("Change ALL occurances of this word"),
337 SpellLink('sqspellIgnore()',
338 _("Ignore this word"),
340 SpellLink('sqspellIgnoreAll()',
341 _("Ignore ALL occurances this word"),
343 SpellLink('sqspellRemember()',
344 _("Add this word to your personal dictionary"),
352 <td colspan="4"><hr /></td>
355 <td colspan="4" align="center" bgcolor="<?php echo $color[9] ?>">
357 echo '<input type="button" value=" '
358 . _("Close and Commit")
359 . ' " onclick="if (confirm(\''
360 . _("The spellcheck is not finished. Really close and commit changes?")
361 . '\')) sqspellCommitChanges()" />'
362 . ' <input type="button" value=" '
363 . _("Close and Cancel")
364 . ' " onclick="if (confirm(\''
365 . _("The spellcheck is not finished. Really close and discard changes?")
366 . '\')) self.close()" />';
379 * AREN'T YOU SUCH A KNOW-IT-ALL!
381 $msg='<form onsubmit="return false"><div style="text-align: center;">' .
382 '<input type="submit" value=" ' . _("Close") .
383 ' " onclick="self.close()" /></div></form>';
384 sqspell_makeWindow(null, _("No errors found"), null, $msg);
392 * vim: syntax=php et ts=4