mirrored from git://git.moodle.org/moodle.git
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
spellchecker.php
240 lines (197 loc) · 7.16 KB
/
spellchecker.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<?php // $Id$
include_once("../../../config.php");
require_login();
header('Content-type: text/html; charset=utf-8');
// Speller pages script http://spellerpages.sourceforge.net/
// Modified by Marc Alier on August 2004 for the integration with moodle
$aspell_prog = escapeshellarg($CFG->aspellpath);
$spellercss = $CFG->wwwroot .'/lib/speller/spellerStyle.css';
$word_win_src = $CFG->wwwroot .'/lib/speller/wordWindow.js';
$textinputs = $_POST['textinputs']; // array
if(!($lang = check_language($aspell_prog))) {
error_handler("No suitable dictionary found installed on your server!");
exit;
}
$aspell_opts = '-a -H --lang='. $lang .' --encoding=utf-8';
$tempfiledir = './';
$input_separator = 'A';
function check_language($cmd) {
/// return users current language if its
/// dictionary is found installed in system
/// and always return english if user's own
/// language is not in the list. If english dictionary
/// isn't found, then false is returned.
global $CFG;
error_reporting(E_ALL); // for debug, final version shouldn't have this...
clearstatcache();
$current_lang = current_language();
$output = '';
if(!($handle = popen(escapeshellarg($cmd) .' dump dicts', 'r'))) {
error_handler("Couldn't create handle!");
exit;
}
while(!feof($handle)) {
$output .= fread($handle, 1024);
}
@pclose($handle);
$dicts = explode(chr(10), strtolower($output));
if(is_array($dicts)) {
if(in_array($current_lang,$dicts)) {
return $current_lang;
}
}
if (!empty($CFG->editordictionary)) {
return $CFG->editordictionary;
}
return false;
}
// set the JavaScript variable to the submitted text.
// textinputs is an array, each element corresponding to the (url-encoded)
// value of the text control submitted for spell-checking
function print_textinputs_var() {
global $textinputs;
foreach( $textinputs as $key=>$val ) {
// $val = str_replace( "'", "%27", $val );
echo "textinputs[$key] = decodeURIComponent(\"" . $val . "\");\n";
}
}
// make declarations for the text input index
function print_textindex_decl( $text_input_idx ) {
echo "words[$text_input_idx] = [];\n";
echo "suggs[$text_input_idx] = [];\n";
}
// set an element of the JavaScript 'words' array to a misspelled word
function print_words_elem( $word, $index, $text_input_idx ) {
echo "words[$text_input_idx][$index] = '" . escape_quote( $word ) . "';\n";
}
// set an element of the JavaScript 'suggs' array to a list of suggestions
function print_suggs_elem( $suggs, $index, $text_input_idx ) {
echo "suggs[$text_input_idx][$index] = [";
foreach( $suggs as $key=>$val ) {
if( $val ) {
echo "'" . escape_quote( $val ) . "'";
if ( $key+1 < count( $suggs )) {
echo ", ";
}
}
}
echo "];\n";
}
// escape single quote
function escape_quote( $str ) {
return preg_replace ( "/'/", "\\'", $str );
}
// handle a server-side error.
function error_handler( $err ) {
echo "error = '" . escape_quote( $err ) . "';\n";
}
// get the list of misspelled words. Put the results in the javascript words array
// for each misspelled word, get suggestions and put in the javascript suggs array
function print_checker_results() {
global $aspell_prog;
global $aspell_opts;
global $tempfiledir;
global $textinputs;
global $input_separator;
$aspell_err = "";
// create temp file
$tempfile = tempnam( $tempfiledir, 'aspell_data_' );
// open temp file, add the submitted text.
if( $fh = fopen( $tempfile, 'w' )) {
for( $i = 0; $i < count( $textinputs ); $i++ ) {
$text = urldecode( $textinputs[$i] );
$lines = explode( "\n", $text );
fwrite ( $fh, "%\n" ); // exit terse mode
fwrite ( $fh, "^$input_separator\n" );
fwrite ( $fh, "!\n" ); // enter terse mode
foreach( $lines as $key=>$value ) {
// use carat on each line to escape possible aspell commands
fwrite( $fh, "^$value\n" );
}
}
fclose( $fh );
// exec aspell command - redirect STDERR to STDOUT
$cmd = "$aspell_prog $aspell_opts < $tempfile 2>&1";
if( $aspellret = shell_exec( $cmd )) {
$linesout = explode( "\n", $aspellret );
$index = 0;
$text_input_index = -1;
// parse each line of aspell return
foreach( $linesout as $key=>$val ) {
$chardesc = substr( $val, 0, 1 );
// if '&', then not in dictionary but has suggestions
// if '#', then not in dictionary and no suggestions
// if '*', then it is a delimiter between text inputs
// if '@' then version info
if( $chardesc == '&' || $chardesc == '#' ) {
$line = explode( " ", $val, 5 );
print_words_elem( $line[1], $index, $text_input_index );
if( isset( $line[4] )) {
$suggs = explode( ", ", $line[4] );
} else {
$suggs = array();
}
print_suggs_elem( $suggs, $index, $text_input_index );
$index++;
} elseif( $chardesc == '*' ) {
$text_input_index++;
print_textindex_decl( $text_input_index );
$index = 0;
} elseif( $chardesc != '@' && $chardesc != "" ) {
// assume this is error output
$aspell_err .= $val;
}
}
if( $aspell_err ) {
$aspell_err = "Error executing `$cmd`\\n$aspell_err";
error_handler( $aspell_err );
}
} else {
error_handler( "System error: Aspell program execution failed (`$cmd`)" );
}
} else {
error_handler( "System error: Could not open file '$tempfile' for writing" );
}
// close temp file, delete file
unlink( $tempfile );
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="<?php echo $spellercss ?>" />
<script language="javascript" src="<?php echo $word_win_src ?>"></script>
<script language="javascript">
var suggs = new Array();
var words = new Array();
var textinputs = new Array();
var error;
<?php
print_textinputs_var();
print_checker_results();
?>
var wordWindowObj = new wordWindow();
wordWindowObj.originalSpellings = words;
wordWindowObj.suggestions = suggs;
wordWindowObj.textInputs = textinputs;
function init_spell() {
// check if any error occured during server-side processing
if( error ) {
alert( error );
} else {
// call the init_spell() function in the parent frameset
if (parent.frames.length) {
parent.init_spell( wordWindowObj );
} else {
alert('This page was loaded outside of a frameset. It might not display properly');
}
}
}
</script>
</head>
<body onLoad="init_spell();">
<script type="text/javascript">
wordWindowObj.writeBody();
</script>
</body>
</html>