Ticket #2282: spellchecker.cfm

File spellchecker.cfm, 8.8 KB (added by Mark Woods, 16 years ago)
Line 
1<cfsetting enablecfoutputonly="true">
2<!---
3This code uses a CF User Defined Function and should work in CF version 5.0
4and up without alteration.
5
6Also if you are hosting your site at an ISP, you will have to check with them
7to see if the use of <CFEXECUTE> is allowed. In most cases ISP will not allow
8the use of that tag for security reasons. Clients would be able to access each
9others files in certain cases.
10--->
11
12<!---
13Updated by Mark Woods - 17 April 2008
14* Added support for UNIX OSes (assumes that cf can execute sh with -c option).
15* Automatically determine Aspell language from CF locale.
16* Upadated code so it should work in CF5 (previous code would not have worked
17with CF5 because it doesn't support UTF8 and the charset attribute of cffile
18was only introduced in CF6, it makes CF5 throw up into a champagne glass - classy!)
19--->
20
21<cflock type="readonly" scope="server" timeout="3" throwontimeout="true">
22<cfset osName = server.os.name>
23<cfset cfMajorVersion = listFirst(server.coldFusion.productVersion,",.")>
24</cflock>
25
26<cfscript>
27        // set paths to the aspell executable
28        windows_executable = "C:\Program Files\Aspell\bin\aspell.exe";
29        unix_executable = "aspell";
30       
31        // what encoding do we use (utf-8 where possible)
32        if ( cfMajorVersion gte 6 ) {
33                encoding = "utf-8";
34        } else {
35                encoding = "iso8859-1";
36        }
37       
38        // get aspell language from cf locale
39        // note: I'm assuming that the java locale can be used as the aspell language as long as relevant dictionary installed
40        cfLocale = getLocale();
41        if ( len(cfLocale) eq 2 ) {
42                // we just have a language code, that'll do grand
43                aspell_lang = cfLocale;
44        } else if ( reFind("^[a-zA-Z]{2}_[a-zA-Z]{2}",cfLocale) ) {
45                // java locale, remove any variant info from the locale, we just want the language and country codes
46                aspell_lang = left(cfLocale,5);
47        } else {
48                // old skool cf locale from CF6.1 or before (e.g. English (UK)) - convert to jvm locale
49                stJavaLocales = structNew();
50                stJavaLocales.zh_CH = "Chinese (China)";
51                stJavaLocales.zh_HK = "Chinese (Hong Kong)";
52                stJavaLocales.zh_TW = "Chinese (Taiwan)";
53                stJavaLocales.nl_BE = "Dutch (Belgian)";
54                stJavaLocales.nl_NL = "Dutch (Standard)";
55                stJavaLocales.en_AU = "English (Australian)";
56                stJavaLocales.en_CA = "English (Canadian)";
57                stJavaLocales.en_NZ = "English (New Zealand)";
58                stJavaLocales.en_GB = "English (UK)";
59                stJavaLocales.en_US = "English (US)";
60                stJavaLocales.fr_BE = "French (Belgian)";
61                stJavaLocales.fr_CA = "French (Canadian)";
62                stJavaLocales.fr_FR = "French (Standard)";
63                stJavaLocales.fr_CH = "French (Swiss)";
64                stJavaLocales.de_AT = "German (Austrian)";
65                stJavaLocales.de_DE = "German (Standard)";
66                stJavaLocales.de_CH = "German (Swiss)";
67                stJavaLocales.it_IT = "Italian (Standard)";
68                stJavaLocales.it_CH = "Italian (Standard)";
69                stJavaLocales.ja_JP = "Japanese";
70                stJavaLocales.ko_KR = "Korean";
71                stJavaLocales.no_NO = "Norwegian (Bokmal)";
72                stJavaLocales.no_NO = "Norwegian (Nynorsk)";
73                stJavaLocales.pt_BR = "Portuguese (Brazilian)";
74                stJavaLocales.pt_PT = "Portuguese (Standard)";
75                stJavaLocales.es_MX = "Spanish (Mexican)";
76                stJavaLocales.es_ES = "Spanish (Modern)";
77                stJavaLocales.es_ES = "Spanish (Standard)";
78                stJavaLocales.sv_SE = "Swedish";
79               
80                aKeys = structFindValue(stJavaLocales,cfLocale);
81                if ( arrayIsEmpty(aKeys) ) {
82                        aspell_lang = "en_US";
83                } else {
84                        aspell_lang = aKeys[1]["key"];
85                        aspell_lang = lCase(left(aspell_lang,2)) & "_" & uCase(right(aspell_lang,2));
86                }
87        }
88</cfscript>
89
90<cfset aspell_opts  = "-a --lang=#aspell_lang# --encoding=#encoding# -H --rem-sgml-check=alt">
91<cfset tempfile_in  = GetTempFile(GetTempDirectory(), "spell_")>
92<cfset tempfile_out = GetTempFile(GetTempDirectory(), "spell_")>
93<cfset spellercss   = "../spellerStyle.css">
94<cfset word_win_src = "../wordWindow.js">
95
96<cfset form.checktext = form["textinputs[]"]>
97
98<!--- make no difference between URL and FORM scopes --->
99<cfparam name="url.checktext"  default="">
100<cfparam name="form.checktext" default="#url.checktext#">
101
102<!--- Takes care of those pesky smart quotes from MS apps, replaces them with regular quotes --->
103<cfset submitted_text = ReplaceList(form.checktext,"%u201C,%u201D","%22,%22")>
104
105<!--- submitted_text now is ready for processing --->
106
107<!--- use carat on each line to escape possible aspell commands --->
108<cfset text = "">
109<cfset CRLF = Chr(13) & Chr(10)>
110
111<cfloop list="#submitted_text#" index="field" delimiters=",">
112        <cfset text = text & "%"  & CRLF
113                      & "^A" & CRLF
114                      & "!"  & CRLF>
115        <!--- Strip all tags for the text. (by FredCK - #339 / #681) --->
116        <cfset field = REReplace(URLDecode(field), "<[^>]+>", " ", "all")>
117        <cfloop list="#field#" index="line" delimiters="#CRLF#">
118                <cfset text = ListAppend(text, "^" & Trim(JSStringFormat(line)), CRLF)>
119        </cfloop>
120</cfloop>
121
122<!--- create temp file from the submitted text, this will be passed to aspell to be check for misspelled words --->
123<cftry>
124        <!--- cfmx --->
125        <cffile action="write" file="#tempfile_in#" output="#text#" charset="utf-8">
126<cfcatch>
127        <!--- cf5 --->
128        <cffile action="write" file="#tempfile_in#" output="#text#">
129</cfcatch>
130</cftry>
131
132
133<!--- execute aspell in an UTF-8 console and redirect output to a file --->
134<cfif findNoCase("windows",osName)>
135               
136        <cfexecute name="cmd.exe" arguments='/c type "#tempfile_in#" | "#windows_executable#" #aspell_opts# > "#tempfile_out#"' timeout="3"></cfexecute>
137
138<cfelse>
139
140        <cfexecute name="sh" arguments='-c "#unix_executable# #aspell_opts# < #tempfile_in# > #tempfile_out#"' timeout="3"></cfexecute>
141       
142</cfif>
143
144<!--- read output file for further processing --->
145<cftry>
146        <!--- cfmx --->
147        <cffile action="read" file="#tempfile_out#" variable="food" charset="utf-8">
148<cfcatch>
149        <!--- cf5 --->
150        <cffile action="read" file="#tempfile_out#" variable="food">
151</cfcatch>
152</cftry>
153
154<!--- remove temp files --->
155<cffile action="delete" file="#tempfile_in#">
156<cffile action="delete" file="#tempfile_out#">
157
158<cfset texts = StructNew()>
159<cfset texts.textinputs = "">
160<cfset texts.words      = "">
161<cfset texts.abort      = "">
162
163<!--- Generate Text Inputs --->
164<cfset i = 0>
165<cfloop list="#submitted_text#" index="textinput">
166  <cfset texts.textinputs = ListAppend(texts.textinputs, 'textinputs[#i#] = decodeURIComponent("#textinput#");', CRLF)>
167  <cfset i = i + 1>
168</cfloop>
169
170<!--- Generate Words Lists --->
171<cfset word_cnt  = 0>
172<cfset input_cnt = -1>
173<cfloop list="#food#" index="aspell_line" delimiters="#CRLF#">
174    <cfset leftChar = Left(aspell_line, 1)>
175        <cfif leftChar eq "*">
176                        <cfset input_cnt   = input_cnt + 1>
177                        <cfset word_cnt    = 0>
178                        <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#] = [];", CRLF)>
179                        <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#] = [];", CRLF)>
180    <cfelse>
181        <cfif leftChar eq "&" or leftChar eq "##">
182                        <!--- word that misspelled --->
183                        <cfset bad_word    = Trim(ListGetAt(aspell_line, 2, " "))>
184                        <cfset bad_word    = Replace(bad_word, "'", "\'", "ALL")>
185                        <!--- sugestions --->
186                        <cfset sug_list    = Trim(ListRest(aspell_line, ":"))>
187                        <cfset sug_list    = ListQualify(Replace(sug_list, "'", "\'", "ALL"), "'")>
188                        <!--- javascript --->
189                        <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#][#word_cnt#] = '#bad_word#';", CRLF)>
190                        <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#][#word_cnt#] = [#sug_list#];", CRLF)>
191                        <cfset word_cnt    = word_cnt + 1>
192                </cfif>
193     </cfif>
194</cfloop>
195
196<cfif texts.words eq "">
197  <cfset texts.abort = "alert('Spell check complete.\n\nNo misspellings found.'); top.window.close();">
198</cfif>
199
200<cfcontent type="text/html; charset=#encoding#">
201
202<cfoutput><html>
203<head>
204<meta http-equiv="Content-Type" content="text/html; charset=#encoding#">
205<link rel="stylesheet" type="text/css" href="#spellercss#" />
206<script language="javascript" src="#word_win_src#"></script>
207<script language="javascript">
208var suggs      = new Array();
209var words      = new Array();
210var textinputs = new Array();
211var error;
212
213#texts.textinputs##CRLF#
214#texts.words#
215#texts.abort#
216
217var wordWindowObj = new wordWindow();
218wordWindowObj.originalSpellings = words;
219wordWindowObj.suggestions = suggs;
220wordWindowObj.textInputs = textinputs;
221
222function init_spell() {
223        // check if any error occured during server-side processing
224        if( error ) {
225                alert( error );
226        } else {
227                // call the init_spell() function in the parent frameset
228                if (parent.frames.length) {
229                        parent.init_spell( wordWindowObj );
230                } else {
231                        alert('This page was loaded outside of a frameset. It might not display properly');
232                }
233        }
234}
235</script>
236
237</head>
238<body onLoad="init_spell();">
239
240<script type="text/javascript">
241wordWindowObj.writeBody();
242</script>
243
244</body>
245</html></cfoutput>
246<cfsetting enablecfoutputonly="false">
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy