try to fix some minor dropdown bugs
[potlatch2.git] / com / adobe / protocols / dict / Dict.as
1 package com.adobe.protocols.dict\r
2 {\r
3         import com.adobe.protocols.dict.events.*;\r
4         import com.adobe.protocols.dict.util.*;\r
5         \r
6         import flash.events.Event;\r
7         import flash.events.EventDispatcher;\r
8         import flash.events.IOErrorEvent;\r
9         import flash.events.ProgressEvent;\r
10         import flash.events.SecurityErrorEvent;\r
11         import flash.net.Socket;\r
12         import mx.rpc.http.HTTPService;\r
13         import mx.rpc.events.ResultEvent;\r
14         import mx.rpc.events.FaultEvent;\r
15         import flash.xml.XMLNode;\r
16         import mx.utils.StringUtil;\r
17 \r
18         public class Dict\r
19                 extends EventDispatcher\r
20         {\r
21                 // Event type names.\r
22                 public static var CONNECTED:String = "connected";\r
23                 public static var DISCONNECTED:String = "disconnected";\r
24                 public static var IO_ERROR:String = IOErrorEvent.IO_ERROR;\r
25                 public static var ERROR:String = "error";\r
26                 public static var SERVERS:String = "servers";\r
27                 public static var DATABASES:String = "databases";\r
28                 public static var MATCH_STRATEGIES:String = "matchStrategies";\r
29                 public static var DEFINITION:String = "definition";\r
30                 public static var DEFINITION_HEADER:String = "definitionHeader";\r
31                 public static var MATCH:String = "match";\r
32                 public static var NO_MATCH:String = "noMatch";\r
33 \r
34                 public static var FIRST_MATCH:uint = 0;\r
35                 public static var ALL_DATABASES:uint = 1;\r
36 \r
37                 private var socket:SocketHelper;\r
38                 \r
39                 private var dbShortList:Boolean;\r
40 \r
41                 public function Dict()\r
42                 {\r
43                         this.socket = new SocketHelper();\r
44                         this.socket.addEventListener(Event.CONNECT, connected);\r
45                         this.socket.addEventListener(Event.CLOSE, disconnected);\r
46                         this.socket.addEventListener(SocketHelper.COMPLETE_RESPONSE, incomingData);\r
47                         this.socket.addEventListener(IOErrorEvent.IO_ERROR, ioError);\r
48                         this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);\r
49                 }\r
50 \r
51                 public function connect(server:String, port:uint = 2628):void\r
52                 {\r
53                         if (this.socket.connected)\r
54                         {\r
55                                 this.socket.close();\r
56                         }\r
57                         this.socket.connect(server, port);\r
58                 }\r
59 \r
60                 public function connectThroughProxy(proxyServer:String,\r
61                                                                                         proxyPort:int,\r
62                                                                                         server:String,\r
63                                                                                         port:uint = 2628):void\r
64                 {\r
65                         if (this.socket.connected)\r
66                         {\r
67                                 this.socket.close();\r
68                         }\r
69                         this.socket.setProxyInfo(proxyServer, proxyPort);\r
70                         this.socket.connect(server, port);\r
71                 }\r
72 \r
73                 public function disconnect():void\r
74                 {\r
75                         this.socket.close();\r
76                         this.disconnected(null);\r
77                 }\r
78 \r
79                 public function getServers():void\r
80                 {\r
81                         var http:HTTPService = new HTTPService();\r
82                         http.url = "http://luetzschena-stahmeln.de/dictd/xmllist.php";\r
83                         http.addEventListener(ResultEvent.RESULT, incomingServerXML);\r
84                         http.addEventListener(FaultEvent.FAULT, httpError);\r
85                         http.resultFormat = HTTPService.RESULT_FORMAT_E4X;\r
86                         http.send();\r
87                 }\r
88 \r
89                 public function getDatabases(shortList:Boolean=true):void\r
90                 {\r
91                         this.dbShortList = shortList;\r
92                         this.socket.writeUTFBytes("show db\r\n");\r
93                         this.socket.flush();\r
94                 }\r
95 \r
96                 public function getMatchStrategies():void\r
97                 {\r
98                         this.socket.writeUTFBytes("show strat\r\n");\r
99                         this.socket.flush();\r
100                 }\r
101 \r
102                 public function match(database:String, term:String, scope:String="prefix"):void\r
103                 {\r
104                         this.socket.writeUTFBytes("match " + database + " " + scope + " \"" + term + "\"\r\n");\r
105                         this.socket.flush();\r
106                 }\r
107 \r
108                 public function define(database:String, term:String):void\r
109                 {\r
110                         this.socket.writeUTFBytes("define " + database + " \"" + term + "\"\r\n");\r
111                         this.socket.flush();\r
112                 }\r
113 \r
114                 public function lookup(term:String, scope:uint):void\r
115                 {\r
116                         var flag:String;\r
117                         if (scope == Dict.ALL_DATABASES)\r
118                         {\r
119                                 flag = "*";\r
120                         }\r
121                         else if (scope == Dict.FIRST_MATCH)\r
122                         {\r
123                                 flag = "!";\r
124                         }\r
125                         this.socket.writeUTFBytes("define " + flag + " \"" + term + "\"\r\n");\r
126                         this.socket.flush();\r
127                 }\r
128 \r
129                 //// Private functions ////\r
130 \r
131                 private function connected(event:Event):void\r
132                 {\r
133                 // Wait to dispatch an event until we get the 220 response.\r
134         }\r
135 \r
136                 private function disconnected(event:Event):void\r
137                 {\r
138                 dispatchEvent(new DisconnectedEvent());\r
139         }\r
140 \r
141                 private function incomingServerXML(event:ResultEvent):void\r
142                 {\r
143                         var dictd:Namespace = new Namespace("http://www.luetzschena-stahmeln.de/dictd/");\r
144                         var result:XML = event.result as XML;\r
145                         var server:String, description:String;\r
146                         var servers:Array = new Array();\r
147                         for each (var serverNode:XML in result.dictd::server)\r
148                         {\r
149                                 server = serverNode.dictd::dictdurl;\r
150                                 description = serverNode.dictd::description;\r
151                                 if (StringUtil.trim(server).length != 0 &&\r
152                                         StringUtil.trim(description).length != 0)\r
153                                 {\r
154                                         var dServer:DictionaryServer = new DictionaryServer();\r
155                                         dServer.server = server.replace("dict://", "");\r
156                                         dServer.description = description;\r
157                                         servers.push(dServer);\r
158                                 }\r
159                         }\r
160                         var dEvent:DictionaryServerEvent = new DictionaryServerEvent();\r
161                         dEvent.servers = servers;\r
162                         dispatchEvent(dEvent);\r
163                 }\r
164 \r
165                 private function incomingData(event:CompleteResponseEvent):void\r
166                 {                       \r
167                         var rawResponse:String = event.response;\r
168                         var response:Response = this.parseRawResponse(rawResponse);\r
169                         var responseCode:uint = response.code;\r
170                         if (responseCode == 552) // no matches\r
171                         {\r
172                                 throwNoMatchEvent(response);\r
173                         }\r
174                         else if (responseCode >= 400 && responseCode <= 599) // error\r
175                         {\r
176                                 throwErrorEvent(response);\r
177                         }\r
178                         else if (responseCode == 220) // successful connection\r
179                         {\r
180                                 dispatchEvent(new ConnectedEvent());\r
181                         }\r
182                         else if (responseCode == 110) // databases are being returned\r
183                         {\r
184                                 throwDatabasesEvent(response);                          \r
185                         }\r
186                         else if (responseCode == 111) // matches strategies\r
187                         {\r
188                                 throwMatchStrategiesEvent(response);\r
189                         }\r
190                         else if (responseCode == 152) // matches\r
191                         {\r
192                                 throwMatchEvent(response);\r
193                         }\r
194                         else if (responseCode == 150)\r
195                         {\r
196                                 throwDefinitionHeaderEvent(response);\r
197                         }\r
198                         else if (responseCode == 151)\r
199                         {\r
200                                 throwDefinitionEvent(response);\r
201                         }\r
202         }\r
203 \r
204         private function ioError(event:IOErrorEvent):void\r
205         {\r
206                         dispatchEvent(event);\r
207         }\r
208 \r
209         private function httpError(event:FaultEvent):void\r
210         {\r
211                 trace("httpError!");\r
212         }\r
213 \r
214         private function securityError(event:SecurityErrorEvent):void\r
215         {\r
216                 trace("security error!");\r
217                 trace(event.text);\r
218         }\r
219 \r
220         // Dispatch new events.\r
221 \r
222         private function throwDatabasesEvent(response:Response):void\r
223         {\r
224                         var databases:Array = new Array();\r
225                         var responseArray:Array = response.body.split("\r\n");\r
226                 for each (var line:String in responseArray)\r
227                 {\r
228                         var name:String = line.substring(0, line.indexOf(" "));\r
229                         if (name == "--exit--")\r
230                         {\r
231                                 if (this.dbShortList)\r
232                                 {\r
233                                         break;\r
234                                 }\r
235                                 continue;\r
236                         }\r
237                         var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,"");\r
238                         databases.push(new Database(name, description));\r
239                 }\r
240                 var event:DatabaseEvent = new DatabaseEvent();\r
241                 event.databases = databases;\r
242                 dispatchEvent(event);\r
243         }\r
244 \r
245         private function throwMatchStrategiesEvent(response:Response):void\r
246         {\r
247                         var strategies:Array = new Array();\r
248                         var responseArray:Array = response.body.split("\r\n");\r
249                 for each (var line:String in responseArray)\r
250                 {\r
251                         var name:String = line.substring(0, line.indexOf(" "));\r
252                         var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,"");\r
253                         strategies.push(new MatchStrategy(name, description));\r
254                 }\r
255                 var event:MatchStrategiesEvent = new MatchStrategiesEvent();\r
256                 event.strategies = strategies;\r
257                 dispatchEvent(event);\r
258         }\r
259 \r
260         private function throwMatchEvent(response:Response):void\r
261         {\r
262                         var matches:Array = new Array();\r
263                         var responseArray:Array = response.body.split("\r\n");\r
264                 for each (var line:String in responseArray)\r
265                 {\r
266                         var match:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,"");\r
267                         matches.push(match);\r
268                 }\r
269                 var event:MatchEvent = new MatchEvent();\r
270                 event.matches = matches;\r
271                 dispatchEvent(event);\r
272         }\r
273 \r
274         private function throwErrorEvent(response:Response):void\r
275         {\r
276                 var event:ErrorEvent = new ErrorEvent();\r
277                 event.code = response.code;\r
278                 event.message = response.headerText;\r
279                         dispatchEvent(event);\r
280         }\r
281 \r
282         private function throwNoMatchEvent(response:Response):void\r
283         {\r
284                         dispatchEvent(new NoMatchEvent());\r
285         }\r
286 \r
287         private function throwDefinitionHeaderEvent(response:Response):void\r
288         {\r
289                         var event:DefinitionHeaderEvent = new DefinitionHeaderEvent();\r
290                         event.definitionCount = uint(response.headerText.substring(0, response.headerText.indexOf(" ")));\r
291                         dispatchEvent(event);\r
292         }\r
293 \r
294         private function throwDefinitionEvent(response:Response):void\r
295         {\r
296                 var event:DefinitionEvent = new DefinitionEvent();\r
297                 var def:Definition = new Definition();\r
298                 var headerText:String = response.headerText;\r
299                 var tokens:Array = headerText.match(/"[^"]+"/g);\r
300                 def.term = String(tokens[0]).replace(/"/g, "");\r
301                 def.database = String(tokens[1]).replace(/"/g, "");\r
302                 def.definition = response.body;\r
303                 event.definition = def;\r
304                         dispatchEvent(event);\r
305         }\r
306 \r
307         private function parseRawResponse(rawResponse:String):Response\r
308         {\r
309                 var response:Response = new Response();\r
310                 var fullHeader:String;\r
311                 if (rawResponse.indexOf("\r\n") != -1)\r
312                 {\r
313                         fullHeader = rawResponse.substring(0, rawResponse.indexOf("\r\n"));\r
314                 }\r
315                 else\r
316                 {\r
317                         fullHeader = rawResponse;\r
318                 }\r
319                 var responseCodeMatch:Array = fullHeader.match(/^\d{3}/);\r
320                 response.code = uint(responseCodeMatch[0]);\r
321                 response.headerText = fullHeader.substring(fullHeader.indexOf(" ")+1, fullHeader.length);\r
322                         var body:String = rawResponse.substring(rawResponse.indexOf("\r\n")+2, rawResponse.length);\r
323                         body = body.replace(/\r\n\.\./, "\r\n.");\r
324                         response.body = body;\r
325                 return response;\r
326         }\r
327         }\r
328 }