Tyler: This is not very original but should do the trick
[squirrelmail.git] / plugins / squirrelspell / sqspell_functions.php
1 <?php
2
3 /**
4 ** sqspell_functions.php -- All SquirrelSpell-wide functions are in this file.
5 **
6 ** Copyright (c) 1999-2001 The SquirrelMail development team
7 ** Licensed under the GNU GPL. For full terms see the file COPYING.
8 **
9 **
10 **
11 ** $Id$
12 **/
13
14 function sqspell_makePage($title, $scriptsrc, $body){
15 /*
16 ** GUI wrap-around for the OPTIONS page.
17 */
18 global $color, $SQSPELL_VERSION, $MOD;
19 displayPageHeader($color, 'None');
20
21 echo "&nbsp;<br>\n";
22 if($scriptsrc) {
23 echo "<script type=\"text/javascript\" src=\"js/$scriptsrc\"></script>\n";
24 }
25 echo '<table width="95%" align="center" border="0" cellpadding="2" cellspacing="0">'.
26 '<tr>'.
27 "<td bgcolor=\"$color[9]\" align=center>".
28 "<strong>$title</strong>".
29 '</td>'.
30 '</tr>'.
31 '<tr><td><hr></td></tr>'.
32 "<tr><td>$body</td></tr>";
33 if ($MOD!="options_main"){
34 // Generate a nice return-to-main link.
35 echo '<tr><td><hr></td></tr>'.
36 '<tr><td align="center"><a href="sqspell_options.php">' .
37 _("Back to &quot;SpellChecker Options&quot; page") . '</a></td></tr>';
38 }
39 echo '<tr><td><hr></td></tr>'.
40 '<tr>'.
41 "<td bgcolor=\"$color[9]\" align=center>".
42 "SquirrelSpell $SQSPELL_VERSION".
43 '</td>'.
44 '</tr>'.
45 '</table>';
46 }
47
48 function sqspell_makeWindow($onload, $title, $scriptsrc, $body){
49
50 /*
51 ** GUI wrap-around for the pop-up window interface.
52 */
53 global $color, $SQSPELL_VERSION, $theme_css;
54
55 echo "<html>\n".
56 "<head>\n".
57 "<title>$title</title>\n";
58 if ($theme_css != "") {
59 echo "<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"$theme_css\">\n";
60 }
61 if ($scriptsrc){
62 echo "<script type=\"text/javascript\" src=\"js/$scriptsrc\"></script>\n";
63 }
64 echo "</head>\n".
65 "<body text=\"$color[8]\" bgcolor=\"$color[4]\" link=\"$color[7]\" vlink=\"$color[7]\" alink=\"$color[7]\"";
66 if ($onload) {
67 echo " onload=\"$onload\"";
68 }
69 echo '>'.
70 '<table width="100%" border="0" cellpadding="2">'.
71 '<tr>'.
72 "<td bgcolor=\"$color[9]\" align=center>".
73 "<strong>$title</strong>".
74 '</td>'.
75 '</tr>'.
76 '<tr><td><hr></td></tr>'.
77 '<tr>'.
78 "<td>$body</td>".
79 '</tr>'.
80 '<tr><td><hr></td></tr>'.
81 '<tr>'.
82 "<td bgcolor=\"$color[9]\" align=center>".
83 "SquirrelSpell $SQSPELL_VERSION".
84 '</td>'.
85 '</tr>'.
86 '</table>'.
87 "</body>\n</html>\n";
88 }
89
90 function sqspell_crypto($mode, $ckey, $input){
91 //
92 // This function does the encryption and decryption of the user
93 // dictionary. It is only available when PHP is compiled
94 // --with-mcrypt. See doc/CRYPTO for more information.
95 //
96 if (!function_exists(mcrypt_generic)) {
97 return 'PANIC';
98 }
99 $td = mcrypt_module_open(MCRYPT_Blowfish, "", MCRYPT_MODE_ECB, "");
100 $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);
101 mcrypt_generic_init($td, $ckey, $iv);
102 switch ($mode){
103 case 'encrypt':
104 $crypto = mcrypt_generic($td, $input);
105 break;
106 case 'decrypt':
107 $crypto = mdecrypt_generic($td, $input);
108 // See if it decrypted successfully. If so, it should contain
109 // the string "# SquirrelSpell".
110 if (!strstr($crypto, "# SquirrelSpell"))
111 $crypto='PANIC';
112 break;
113 }
114 mcrypt_generic_end ($td);
115 return $crypto;
116 }
117
118 function sqspell_upgradeWordsFile($words_string){
119 /*
120 ** This function transparently upgrades the 0.2 dictionary format to
121 ** 0.3, since user-defined languages have been added in 0.3 and
122 ** the new format keeps user dictionaries selection in the file.
123 */
124 global $SQSPELL_APP_DEFAULT, $SQSPELL_VERSION;
125
126 /* Define just one dictionary for this user -- the default.
127 ** If the user wants more, s/he can set them up in personal
128 ** preferences. See doc/UPGRADING for more info.
129 */
130 $new_words_string=substr_replace($words_string, "# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: $SQSPELL_APP_DEFAULT\n# $SQSPELL_APP_DEFAULT", 0, strpos($words_string, "\n")) . "# End\n";
131 sqspell_writeWords($new_words_string);
132 return $new_words_string;
133 }
134
135 function sqspell_getSettings($words){
136 /*
137 ** Right now it just returns an array with the dictionaries
138 ** available to the user for spell-checking. It will probably
139 ** do more in the future, as features are added.
140 */
141 global $SQSPELL_APP, $SQSPELL_APP_DEFAULT;
142 if (sizeof($SQSPELL_APP) > 1){
143 // OK, so there are more than one dictionary option.
144 // Now load the user prefs.
145 if(!$words)
146 $words=sqspell_getWords();
147 if ($words){
148 // find which dictionaries user wants to use
149 preg_match("/# LANG: (.*)/i", $words, $matches);
150 $langs=explode(", ", $matches[1]);
151 } else {
152 // User doesn't have a personal dictionary. Set him up with
153 // a default setting.
154 $langs[0]=$SQSPELL_APP_DEFAULT;
155 }
156 } else {
157 // There is only one dictionary defined system-wide.
158 $langs[0]=$SQSPELL_APP_DEFAULT;
159 }
160 return $langs;
161 }
162
163 function sqspell_getLang($words, $lang){
164 //
165 // Returns words of a specific user dictionary.
166 //
167 $start=strpos($words, "# $lang\n");
168 if (!$start) return '';
169 $end=strpos($words, "#", $start+1);
170 $lang_words = substr($words, $start, $end-$start);
171 return $lang_words;
172 }
173
174 function sqspell_getWords(){
175 //
176 // This baby operates the user dictionary. If the format is clear-text,
177 // then it just reads the file and returns it. However, if the file is
178 // encrypted, then it decrypts it, checks whether the decryption was
179 // successful, troubleshoots if not, then returns the clear-text dictionary
180 // to the app.
181 //
182 global $SQSPELL_WORDS_FILE, $SQSPELL_CRYPTO;
183 $words="";
184 if (file_exists($SQSPELL_WORDS_FILE)){
185 // Gobble it up.
186 $fp=fopen($SQSPELL_WORDS_FILE, 'r');
187 $words=fread($fp, filesize($SQSPELL_WORDS_FILE));
188 fclose($fp);
189 }
190 // Check if this is an encrypted file by looking for
191 // the string "# SquirrelSpell" in it.
192 if ($words && !strstr($words, "# SquirrelSpell")){
193 // This file is encrypted or mangled. Try to decrypt it.
194 // If fails, raise hell.
195 global $key, $onetimepad, $old_key;
196 if ($old_key) {
197 // an override in case user is trying to decrypt a dictionary
198 // with his old password
199 $clear_key=$old_key;
200 } else {
201 // get user's password (the key).
202 $clear_key = OneTimePadDecrypt($key, $onetimepad);
203 }
204 // decrypt
205 $words=sqspell_crypto("decrypt", $clear_key, $words);
206 if ($words=="PANIC"){
207 // AAAAAAAAAAAH!!!!! OK, ok, breathe!
208 // Let's hope the decryption failed because the user changed his
209 // password. Bring up the option to key in the old password
210 // or wipe the file and start over if everything else fails.
211 $msg='<p>'.
212 '<strong>' . _("ATTENTION:") . '</strong><br>' .
213 _("SquirrelSpell was unable to decrypt your personal dictionary. This is most likely due to the fact that you have changed your mailbox password. In order to proceed, you will have to supply your old password so that SquirrelSpell can decrypt your personal dictionary. It will be re-encrypted with your new password after this.<br>If you haven't encrypted your dictionary, then it got mangled and is no longer valid. You will have to delete it and start anew. This is also true if you don't remember your old password -- without it, the encrypted data is no longer accessible.").
214 '</p>' .
215 '<blockquote>'.
216 '<form method="post" onsubmit="return AYS()">'.
217 '<input type="hidden" name="MOD" value="crypto_badkey">'.
218 '<p><input type="checkbox" name="delete_words" value="ON">' .
219 _("Delete my dictionary and start a new one") . '<br>'.
220 _("Decrypt my dictionary with my old password:") .
221 '<input name="old_key" size=\"10\"></p>'.
222 '</blockquote>'.
223 '<p align="center"><input type="submit" value="' . _("Proceed") . ' &gt;&gt;"></p>'.
224 '</form>';
225 // See if this happened in the pop-up window or when accessing
226 // the SpellChecker options page.
227 global $SCRIPT_NAME;
228 if (strstr($SCRIPT_NAME, "sqspell_options"))
229 sqspell_makePage( _("Error Decrypting Dictionary"), "decrypt_error.js", $msg);
230 else
231 sqspell_makeWindow(null, _("Error Decrypting Dictionary"), "decrypt_error.js", $msg);
232 exit;
233 } else {
234 // OK! Phew. Set the encryption flag to true so we can later on
235 // encrypt it again before saving to HDD.
236 $SQSPELL_CRYPTO=true;
237 }
238 } else {
239 // No encryption is used. Set $SQSPELL_CRYPTO to false, in case we have to
240 // save the dictionary later.
241 $SQSPELL_CRYPTO=false;
242 }
243 // Check if we need to upgrade the dictionary from version 0.2.x
244 if (strstr($words, "Dictionary v0.2")) $words=sqspell_upgradeWordsFile($words);
245 return $words;
246 }
247
248 function sqspell_writeWords($words){
249 //
250 // Writes user dictionary into the $username.words file, then changes mask
251 // to 0600. If encryption is needed -- does that, too.
252 //
253 global $SQSPELL_WORDS_FILE, $SQSPELL_CRYPTO;
254 // if $words is empty, create a template entry.
255 if (!$words) $words=sqspell_makeDummy();
256 if ($SQSPELL_CRYPTO){
257 // User wants to encrypt the file. So be it.
258 // get his password to use as a key.
259 global $key, $onetimepad;
260 $clear_key=OneTimePadDecrypt($key, $onetimepad);
261 // Try encrypting it. If fails, scream bloody hell.
262 $save_words = sqspell_crypto("encrypt", $clear_key, $words);
263 if ($save_words == 'PANIC'){
264 /*
265 ** AAAAAAAAH! I'm not handling this yet, since obviously
266 ** the admin of the site forgot to compile the MCRYPT support in.
267 ** I will add a handler for this case later, when I can come up
268 ** with some work-around... Right now, do nothing. Let the Admin's
269 ** head hurt.. ;)))
270 */
271 }
272 } else {
273 $save_words = $words;
274 }
275 $fp=fopen($SQSPELL_WORDS_FILE, "w");
276 fwrite($fp, $save_words);
277 fclose($fp);
278 chmod($SQSPELL_WORDS_FILE, 0600);
279 }
280
281 function sqspell_deleteWords(){
282 /*
283 ** so I open the door to my enemies,
284 ** and I ask can we wipe the slate clean,
285 ** but they tell me to please go...
286 ** uhm... Well, this just erases the user dictionary file.
287 */
288 global $SQSPELL_WORDS_FILE;
289 if (file_exists($SQSPELL_WORDS_FILE)) unlink($SQSPELL_WORDS_FILE);
290 }
291
292 function sqspell_makeDummy(){
293 //
294 // Creates an empty user dictionary for the sake of saving prefs or
295 // whatever.
296 //
297 global $SQSPELL_VERSION, $SQSPELL_APP_DEFAULT;
298 $words="# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date('Y-m-d') . "\n# LANG: $SQSPELL_APP_DEFAULT\n# End\n";
299 return $words;
300 }
301
302 /**
303 VERSION:
304 ---------
305 SquirrelSpell version. Don't modify, since it identifies the format
306 of the user dictionary files and messing with this can do ugly
307 stuff. :)
308 **/
309 $SQSPELL_VERSION="v0.3.5";
310
311 ?>