package com.adobe.protocols.dict { import com.adobe.protocols.dict.events.*; import com.adobe.protocols.dict.util.*; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; import flash.net.Socket; import mx.rpc.http.HTTPService; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; import flash.xml.XMLNode; import mx.utils.StringUtil; public class Dict extends EventDispatcher { // Event type names. public static var CONNECTED:String = "connected"; public static var DISCONNECTED:String = "disconnected"; public static var IO_ERROR:String = IOErrorEvent.IO_ERROR; public static var ERROR:String = "error"; public static var SERVERS:String = "servers"; public static var DATABASES:String = "databases"; public static var MATCH_STRATEGIES:String = "matchStrategies"; public static var DEFINITION:String = "definition"; public static var DEFINITION_HEADER:String = "definitionHeader"; public static var MATCH:String = "match"; public static var NO_MATCH:String = "noMatch"; public static var FIRST_MATCH:uint = 0; public static var ALL_DATABASES:uint = 1; private var socket:SocketHelper; private var dbShortList:Boolean; public function Dict() { this.socket = new SocketHelper(); this.socket.addEventListener(Event.CONNECT, connected); this.socket.addEventListener(Event.CLOSE, disconnected); this.socket.addEventListener(SocketHelper.COMPLETE_RESPONSE, incomingData); this.socket.addEventListener(IOErrorEvent.IO_ERROR, ioError); this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError); } public function connect(server:String, port:uint = 2628):void { if (this.socket.connected) { this.socket.close(); } this.socket.connect(server, port); } public function connectThroughProxy(proxyServer:String, proxyPort:int, server:String, port:uint = 2628):void { if (this.socket.connected) { this.socket.close(); } this.socket.setProxyInfo(proxyServer, proxyPort); this.socket.connect(server, port); } public function disconnect():void { this.socket.close(); this.disconnected(null); } public function getServers():void { var http:HTTPService = new HTTPService(); http.url = "http://luetzschena-stahmeln.de/dictd/xmllist.php"; http.addEventListener(ResultEvent.RESULT, incomingServerXML); http.addEventListener(FaultEvent.FAULT, httpError); http.resultFormat = HTTPService.RESULT_FORMAT_E4X; http.send(); } public function getDatabases(shortList:Boolean=true):void { this.dbShortList = shortList; this.socket.writeUTFBytes("show db\r\n"); this.socket.flush(); } public function getMatchStrategies():void { this.socket.writeUTFBytes("show strat\r\n"); this.socket.flush(); } public function match(database:String, term:String, scope:String="prefix"):void { this.socket.writeUTFBytes("match " + database + " " + scope + " \"" + term + "\"\r\n"); this.socket.flush(); } public function define(database:String, term:String):void { this.socket.writeUTFBytes("define " + database + " \"" + term + "\"\r\n"); this.socket.flush(); } public function lookup(term:String, scope:uint):void { var flag:String; if (scope == Dict.ALL_DATABASES) { flag = "*"; } else if (scope == Dict.FIRST_MATCH) { flag = "!"; } this.socket.writeUTFBytes("define " + flag + " \"" + term + "\"\r\n"); this.socket.flush(); } //// Private functions //// private function connected(event:Event):void { // Wait to dispatch an event until we get the 220 response. } private function disconnected(event:Event):void { dispatchEvent(new DisconnectedEvent()); } private function incomingServerXML(event:ResultEvent):void { var dictd:Namespace = new Namespace("http://www.luetzschena-stahmeln.de/dictd/"); var result:XML = event.result as XML; var server:String, description:String; var servers:Array = new Array(); for each (var serverNode:XML in result.dictd::server) { server = serverNode.dictd::dictdurl; description = serverNode.dictd::description; if (StringUtil.trim(server).length != 0 && StringUtil.trim(description).length != 0) { var dServer:DictionaryServer = new DictionaryServer(); dServer.server = server.replace("dict://", ""); dServer.description = description; servers.push(dServer); } } var dEvent:DictionaryServerEvent = new DictionaryServerEvent(); dEvent.servers = servers; dispatchEvent(dEvent); } private function incomingData(event:CompleteResponseEvent):void { var rawResponse:String = event.response; var response:Response = this.parseRawResponse(rawResponse); var responseCode:uint = response.code; if (responseCode == 552) // no matches { throwNoMatchEvent(response); } else if (responseCode >= 400 && responseCode <= 599) // error { throwErrorEvent(response); } else if (responseCode == 220) // successful connection { dispatchEvent(new ConnectedEvent()); } else if (responseCode == 110) // databases are being returned { throwDatabasesEvent(response); } else if (responseCode == 111) // matches strategies { throwMatchStrategiesEvent(response); } else if (responseCode == 152) // matches { throwMatchEvent(response); } else if (responseCode == 150) { throwDefinitionHeaderEvent(response); } else if (responseCode == 151) { throwDefinitionEvent(response); } } private function ioError(event:IOErrorEvent):void { dispatchEvent(event); } private function httpError(event:FaultEvent):void { trace("httpError!"); } private function securityError(event:SecurityErrorEvent):void { trace("security error!"); trace(event.text); } // Dispatch new events. private function throwDatabasesEvent(response:Response):void { var databases:Array = new Array(); var responseArray:Array = response.body.split("\r\n"); for each (var line:String in responseArray) { var name:String = line.substring(0, line.indexOf(" ")); if (name == "--exit--") { if (this.dbShortList) { break; } continue; } var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); databases.push(new Database(name, description)); } var event:DatabaseEvent = new DatabaseEvent(); event.databases = databases; dispatchEvent(event); } private function throwMatchStrategiesEvent(response:Response):void { var strategies:Array = new Array(); var responseArray:Array = response.body.split("\r\n"); for each (var line:String in responseArray) { var name:String = line.substring(0, line.indexOf(" ")); var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); strategies.push(new MatchStrategy(name, description)); } var event:MatchStrategiesEvent = new MatchStrategiesEvent(); event.strategies = strategies; dispatchEvent(event); } private function throwMatchEvent(response:Response):void { var matches:Array = new Array(); var responseArray:Array = response.body.split("\r\n"); for each (var line:String in responseArray) { var match:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); matches.push(match); } var event:MatchEvent = new MatchEvent(); event.matches = matches; dispatchEvent(event); } private function throwErrorEvent(response:Response):void { var event:ErrorEvent = new ErrorEvent(); event.code = response.code; event.message = response.headerText; dispatchEvent(event); } private function throwNoMatchEvent(response:Response):void { dispatchEvent(new NoMatchEvent()); } private function throwDefinitionHeaderEvent(response:Response):void { var event:DefinitionHeaderEvent = new DefinitionHeaderEvent(); event.definitionCount = uint(response.headerText.substring(0, response.headerText.indexOf(" "))); dispatchEvent(event); } private function throwDefinitionEvent(response:Response):void { var event:DefinitionEvent = new DefinitionEvent(); var def:Definition = new Definition(); var headerText:String = response.headerText; var tokens:Array = headerText.match(/"[^"]+"/g); def.term = String(tokens[0]).replace(/"/g, ""); def.database = String(tokens[1]).replace(/"/g, ""); def.definition = response.body; event.definition = def; dispatchEvent(event); } private function parseRawResponse(rawResponse:String):Response { var response:Response = new Response(); var fullHeader:String; if (rawResponse.indexOf("\r\n") != -1) { fullHeader = rawResponse.substring(0, rawResponse.indexOf("\r\n")); } else { fullHeader = rawResponse; } var responseCodeMatch:Array = fullHeader.match(/^\d{3}/); response.code = uint(responseCodeMatch[0]); response.headerText = fullHeader.substring(fullHeader.indexOf(" ")+1, fullHeader.length); var body:String = rawResponse.substring(rawResponse.indexOf("\r\n")+2, rawResponse.length); body = body.replace(/\r\n\.\./, "\r\n."); response.body = body; return response; } } }