Fixing security vulnerability in squirrelspell.
[squirrelmail.git] / plugins / squirrelspell / modules / check_me.mod
1 <?php
2    /**
3     **  check_me.mod.php -- Squirrelspell module
4     **
5     **  Copyright (c) 1999-2002 The SquirrelMail development team
6     **  Licensed under the GNU GPL. For full terms see the file COPYING.
7     **
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.
11     **
12     **  $Id$
13     **/
14
15 function SpellLink( $cod, $tit, $ln ) {
16
17     echo "<td><a href=\"javascript:$cod\"".
18          " title=\"$tit\">$ln</a>".
19          '</td>';
20
21 }
22
23 // Declaring globals for E_ALL.
24 global $sqspell_text, $SQSPELL_APP, $sqspell_use_app, $attachment_dir,
25        $username, $SQSPELL_EREG, $color;
26
27  // Now we explode the lines for three reasons:
28  // 1) So we can ignore lines starting with ">" (reply's)
29  // 2) So we can stop processing when we get to "--" on a single line,
30  //    which means that the signature is starting
31  // 3) So we can add an extra space at the beginning of each line. This way
32  //    ispell/aspell don't treat these as command characters.
33  $sqspell_raw_lines = explode("\n", $sqspell_text);
34  for ($i=0; $i<sizeof($sqspell_raw_lines); $i++){
35    if (trim($sqspell_raw_lines[$i]) == '--') break;
36    if(substr($sqspell_raw_lines[$i], 0, 1) != '>')
37     $sqspell_new_lines[$i] = ' ' . $sqspell_raw_lines[$i];
38     else $sqspell_new_lines[$i] = '';
39  }
40  $sqspell_new_text=implode("\n", $sqspell_new_lines);
41
42  // Define the command used to spellcheck the document.
43  $sqspell_command=$SQSPELL_APP[$sqspell_use_app];
44  // For the simplicity's sake we'll put all text into a file
45  // in attachment_dir directory, then cat it and pipe it to sqspell_command.
46  // There are other ways to do it, including popen(), but it's unidirectional
47  // and no fun at all.
48  // NOTE: This will probably change in future releases of squirrelspell
49  // for privacy reasons.
50  //
51  $floc = "$attachment_dir/$username_sqspell_data.txt";
52  $fp=fopen($floc, 'w');
53  fwrite($fp, $sqspell_new_text);
54  fclose($fp);
55  exec("cat $floc | $sqspell_command", $sqspell_output);
56  unlink($floc);
57
58  // Load the user dictionary.
59  $words=sqspell_getLang(sqspell_getWords(), $sqspell_use_app);
60  // define some variables.
61  $current_line=0;
62  $missed_words=Array();
63  $misses = Array();
64  $locations = Array();
65  $errors=0;
66  // Now we process the output of sqspell_command (ispell or aspell
67  // in ispell compatibility mode, whichever).
68  for ($i=0; $i<sizeof($sqspell_output); $i++){
69   switch (substr($sqspell_output[$i], 0, 1)){
70   case '':
71     // Ispell adds empty lines when an end of line is reached
72     $current_line++;
73     break;
74
75   case '&':
76     // This means there's a misspelled word and a few suggestions.
77     list($left, $right) = explode(": ", $sqspell_output[$i]);
78     $tmparray = explode(" ", $left);
79     $sqspell_word=$tmparray[1];
80     // Check if the word is in user dictionary.
81     if (!$SQSPELL_EREG("\n$sqspell_word\n", $words)){
82      $sqspell_symb=intval($tmparray[3])-1;
83      if (!$misses[$sqspell_word]) {
84         $misses[$sqspell_word] = $right;
85         $missed_words[$errors] = $sqspell_word;
86         $errors++;
87      }
88      if ($locations[$sqspell_word])
89         $locations[$sqspell_word] .= ', ';
90      $locations[$sqspell_word] .= "$current_line:$sqspell_symb";
91     }
92     break;
93
94   case '#':
95     // This means a misspelled word and no suggestions.
96     $tmparray = explode(" ", $sqspell_output[$i]);
97     $sqspell_word=$tmparray[1];
98     // Check if the word is in user dictionary.
99     if (!$SQSPELL_EREG("\n$sqspell_word\n", $words)){
100      $sqspell_symb=intval($tmparray[2])-1;
101      if (!$misses[$sqspell_word]) {
102         $misses[$sqspell_word] = '_NONE';
103         $missed_words[$errors] = $sqspell_word;
104         $errors++;
105      }
106      if ($locations[$sqspell_word]) $locations[$sqspell_word] .= ', ';
107      $locations[$sqspell_word] .= "$current_line:$sqspell_symb";
108     }
109     break;
110   }
111  }
112
113  if ($errors){
114   // So, there are errors
115   // This is the only place where the generic GUI-wrapper is not
116   // called, but generated right here. This is due to the complexity
117   // of the output.
118
119   echo "<html>\n".
120        "<head>\n".
121        '<title>' . _("SquirrelSpell Results") . '</title>';
122     if ($theme_css != '') {
123         echo "<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"$theme_css\">\n";
124     }
125     // Load the spelling errors into JavaScript arrays
126     echo "<script type=\"text/javascript\">\n".
127          "<!--\n";
128
129     $sqspell_lines = explode("\n", $sqspell_text);
130     // All lines of the message
131     echo "var sqspell_lines=new Array();\n";
132     for ($i=0; $i<sizeof($sqspell_lines); $i++){
133       echo "sqspell_lines[$i] = \"" . chop(addslashes($sqspell_lines[$i])) . "\";\n";
134     }
135
136     echo "\n\n";
137     // Misses are all misspelled words
138     echo "var misses=new Array();\n";
139     for ($i=0; $i<sizeof($missed_words); $i++){
140        echo "misses[$i] = \"" . $missed_words[$i] . "\";\n";
141     }
142
143     echo "\n\n";
144     // Suggestions are (guess what!) suggestions for misspellings
145     echo "var suggestions = new Array();\n";
146     $i=0;
147     while (list($word, $value) = each($misses)){
148        if ($value=='_NONE') $value='';
149        echo "suggestions[$i] = \"$value\";\n";
150        $i++;
151     }
152
153     echo "\n\n";
154     // Locations are where those misspellings are located, line:symbol
155     echo "var locations= new Array();\n";
156     $i=0;
157     while (list($word, $value) = each($locations)){
158        echo "locations[$i] = \"$value\";\n";
159        $i++;
160     }
161     // Why isn't there a booger fairy?
162     echo "//-->\n".
163          "</script>\n".
164          "<script src=\"js/check_me.js\" type=\"text/javascript\"></script>\n".
165          "</head>\n";
166
167     echo "<body bgcolor=\"$color[4]\" text=\"$color[8]\" link=\"$color[7]\" alink=\"$color[7]\" vlink=\"$color[7]\" onload=\"populateSqspellForm()\">\n".
168          '<table width="100%" border="0" cellpadding="2">'.
169          "<tr><td bgcolor=\"$color[9]\" align=center><b>";
170     printf( _("Found %s errors"), $errors );
171 ?></b></td></tr>
172    <tr><td><hr></td></tr>
173    <tr><td>
174    <form method="post">
175    <input type="hidden" name="MOD" value="forget_me_not">
176    <input type="hidden" name="words" value="">
177    <input type="hidden" name="sqspell_use_app" value="<?php echo $sqspell_use_app ?>">
178    <table border="0" width="100%">
179     <tr align="center">
180      <td colspan="4">
181 <?php
182     $sptag = "<span style=\"background-color: $color[9]\">";
183     echo $sptag . _("Line with an error:") . '</span>';
184 ?>
185       <br>
186       <textarea name="sqspell_line_area" cols="50" rows="3" wrap="hard" onfocus="this.blur()"></textarea>
187      </td>
188     </tr>
189     <tr valign="middle">
190      <td align="right" width="25%">
191 <?php
192     echo $sptag . _("Error:") . '</span>';
193 ?>
194      </td>
195      <td align="left" width="25%">
196       <input name="sqspell_error" size="10" value="" onfocus="this.blur()">
197      </td>
198      <td align="right" width="25%">
199 <?php
200     echo $sptag . _("Suggestions:") . '</span>';
201 ?>
202      </td>
203      <td align="left" width="25%">
204       <select name="sqspell_suggestion" onchange="if (this.options[this.selectedIndex].value != '_NONE') document.forms[0].sqspell_oruse.value=this.options[this.selectedIndex].value">
205 <?php
206     echo '<option>' . _("Suggestions") . '</option>';
207 ?>
208       </select>
209      </td>
210     </tr>
211     <tr>
212      <td align="right">
213 <?php
214     echo $sptag . _("Change to:") . '</span>';
215 ?>
216      </td>
217      <td align="left">
218       <input name="sqspell_oruse" size="15" value=""
219         onfocus="if(!this.value) this.value=document.forms[0].sqspell_error.value">
220      </td>
221      <td align="right">
222 <?php
223     echo $sptag . _("Occurs times:") . '</span>';
224 ?>
225      </td>
226      <td align="left">
227       <input name="sqspell_likethis" size=3 value="" onfocus="this.blur()">
228      </td>
229     </tr>
230    </td></tr>
231    <tr><td colspan="4"><hr></td></tr>
232     <tr>
233      <td colspan="4">
234       <table border="0" cellpadding="0" cellspacing="3" width="100%">
235 <?php
236     echo "<tr align=center bgcolor=\"$color[9]\">";
237
238     SpellLink( 'sqspellChange()',
239                _("Change this word"),
240                _("Change") );
241     SpellLink( 'sqspellChangeAll()',
242                _("Change ALL occurances of this word"),
243                _("Change All") );
244     SpellLink( 'sqspellIgnore()',
245                _("Ignore this word"),
246                _("Ignore") );
247     SpellLink( 'sqspellIgnoreAll()',
248                _("Ignore ALL occurances this word"),
249                _("Ignore All") );
250     SpellLink( 'sqspellRemember()',
251                _("Add this word to your personal dictionary"),
252                _("Add to Dic") );
253 ?>
254        </tr>
255       </table>
256      </td>
257     </tr>
258     <tr><td colspan="4"><hr></td></tr>
259     <tr>
260 <?php
261
262     echo "<td colspan=4 align=center bgcolor=\"$color[9]\">" .
263          '<input type="button" value="  ' .
264          _("Close and Commit") .
265          '  " onclick="if (confirm(\''.
266          _("The spellcheck is not finished. Really close and commit changes?").
267          '\')) sqspellCommitChanges()">'.
268          ' <input type="button" value="  '.
269          _("Close and Cancel") .
270          '  " onclick="if (confirm(\''.
271          _("The spellcheck is not finished. Really close and discard changes?").
272          '\')) self.close()">';
273 ?>
274      </td>
275     </tr>
276    </table>
277    </form>
278    </td></tr>
279   </table>
280   </body>
281   </html>
282   <?php
283  } else {
284    // AREN'T YOU SUCH A KNOW-IT-ALL!
285    $msg="<form onsubmit=\"return false\"><div align=\"center\"><input type=\"submit\" value=\"  " . _("Close") . "  \" onclick=\"self.close()\"></div></form>";
286    sqspell_makeWindow(null, _("No errors found"), null, $msg);
287  }
288 ?>