mas01mj@732: /* mas01mj@732: Copyright (c) 2009, Adobe Systems Incorporated mas01mj@732: All rights reserved. mas01mj@732: mas01mj@732: Redistribution and use in source and binary forms, with or without mas01mj@732: modification, are permitted provided that the following conditions are mas01mj@732: met: mas01mj@732: mas01mj@732: * Redistributions of source code must retain the above copyright notice, mas01mj@732: this list of conditions and the following disclaimer. mas01mj@732: mas01mj@732: * Redistributions in binary form must reproduce the above copyright mas01mj@732: notice, this list of conditions and the following disclaimer in the mas01mj@732: documentation and/or other materials provided with the distribution. mas01mj@732: mas01mj@732: * Neither the name of Adobe Systems Incorporated nor the names of its mas01mj@732: contributors may be used to endorse or promote products derived from mas01mj@732: this software without specific prior written permission. mas01mj@732: mas01mj@732: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS mas01mj@732: IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, mas01mj@732: THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR mas01mj@732: PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR mas01mj@732: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, mas01mj@732: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, mas01mj@732: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR mas01mj@732: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF mas01mj@732: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING mas01mj@732: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS mas01mj@732: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mas01mj@732: */ mas01mj@732: mas01mj@732: package com.adobe.protocols.dict mas01mj@732: { mas01mj@732: import com.adobe.protocols.dict.events.*; mas01mj@732: import com.adobe.protocols.dict.util.*; mas01mj@732: mas01mj@732: import flash.events.Event; mas01mj@732: import flash.events.EventDispatcher; mas01mj@732: import flash.events.IOErrorEvent; mas01mj@732: import flash.events.ProgressEvent; mas01mj@732: import flash.events.SecurityErrorEvent; mas01mj@732: import flash.net.Socket; mas01mj@732: import mx.rpc.http.HTTPService; mas01mj@732: import mx.rpc.events.ResultEvent; mas01mj@732: import mx.rpc.events.FaultEvent; mas01mj@732: import flash.xml.XMLNode; mas01mj@732: import mx.utils.StringUtil; mas01mj@732: mas01mj@732: public class Dict mas01mj@732: extends EventDispatcher mas01mj@732: { mas01mj@732: // Event type names. mas01mj@732: //public static var CONNECTED:String = "connected"; mas01mj@732: //public static var DISCONNECTED:String = "disconnected"; mas01mj@732: public static var IO_ERROR:String = IOErrorEvent.IO_ERROR; mas01mj@732: //public static var ERROR:String = "error"; mas01mj@732: //public static var SERVERS:String = "servers"; mas01mj@732: //public static var DATABASES:String = "databases"; mas01mj@732: //public static var MATCH_STRATEGIES:String = "matchStrategies"; mas01mj@732: //public static var DEFINITION:String = "definition"; mas01mj@732: //public static var DEFINITION_HEADER:String = "definitionHeader"; mas01mj@732: //public static var MATCH:String = "match"; mas01mj@732: //public static var NO_MATCH:String = "noMatch"; mas01mj@732: mas01mj@732: public static var FIRST_MATCH:uint = 0; mas01mj@732: public static var ALL_DATABASES:uint = 1; mas01mj@732: mas01mj@732: private var socket:SocketHelper; mas01mj@732: mas01mj@732: private var dbShortList:Boolean; mas01mj@732: mas01mj@732: public function Dict() mas01mj@732: { mas01mj@732: this.socket = new SocketHelper(); mas01mj@732: this.socket.addEventListener(Event.CONNECT, connected); mas01mj@732: this.socket.addEventListener(Event.CLOSE, disconnected); mas01mj@732: this.socket.addEventListener(SocketHelper.COMPLETE_RESPONSE, incomingData); mas01mj@732: this.socket.addEventListener(IOErrorEvent.IO_ERROR, ioError); mas01mj@732: this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError); mas01mj@732: } mas01mj@732: mas01mj@732: public function connect(server:String, port:uint = 2628):void mas01mj@732: { mas01mj@732: if (this.socket.connected) mas01mj@732: { mas01mj@732: this.socket.close(); mas01mj@732: } mas01mj@732: this.socket.connect(server, port); mas01mj@732: } mas01mj@732: mas01mj@732: public function connectThroughProxy(proxyServer:String, mas01mj@732: proxyPort:int, mas01mj@732: server:String, mas01mj@732: port:uint = 2628):void mas01mj@732: { mas01mj@732: if (this.socket.connected) mas01mj@732: { mas01mj@732: this.socket.close(); mas01mj@732: } mas01mj@732: this.socket.setProxyInfo(proxyServer, proxyPort); mas01mj@732: this.socket.connect(server, port); mas01mj@732: } mas01mj@732: mas01mj@732: public function disconnect():void mas01mj@732: { mas01mj@732: this.socket.close(); mas01mj@732: this.disconnected(null); mas01mj@732: } mas01mj@732: mas01mj@732: public function getServers():void mas01mj@732: { mas01mj@732: var http:HTTPService = new HTTPService(); mas01mj@732: http.url = "http://luetzschena-stahmeln.de/dictd/xmllist.php"; mas01mj@732: http.addEventListener(ResultEvent.RESULT, incomingServerXML); mas01mj@732: http.addEventListener(FaultEvent.FAULT, httpError); mas01mj@732: http.resultFormat = HTTPService.RESULT_FORMAT_E4X; mas01mj@732: http.send(); mas01mj@732: } mas01mj@732: mas01mj@732: public function getDatabases(shortList:Boolean=true):void mas01mj@732: { mas01mj@732: this.dbShortList = shortList; mas01mj@732: this.socket.writeUTFBytes("show db\r\n"); mas01mj@732: this.socket.flush(); mas01mj@732: } mas01mj@732: mas01mj@732: public function getMatchStrategies():void mas01mj@732: { mas01mj@732: this.socket.writeUTFBytes("show strat\r\n"); mas01mj@732: this.socket.flush(); mas01mj@732: } mas01mj@732: mas01mj@732: public function match(database:String, term:String, scope:String="prefix"):void mas01mj@732: { mas01mj@732: this.socket.writeUTFBytes("match " + database + " " + scope + " \"" + term + "\"\r\n"); mas01mj@732: this.socket.flush(); mas01mj@732: } mas01mj@732: mas01mj@732: public function define(database:String, term:String):void mas01mj@732: { mas01mj@732: this.socket.writeUTFBytes("define " + database + " \"" + term + "\"\r\n"); mas01mj@732: this.socket.flush(); mas01mj@732: } mas01mj@732: mas01mj@732: public function lookup(term:String, scope:uint):void mas01mj@732: { mas01mj@732: var flag:String; mas01mj@732: if (scope == Dict.ALL_DATABASES) mas01mj@732: { mas01mj@732: flag = "*"; mas01mj@732: } mas01mj@732: else if (scope == Dict.FIRST_MATCH) mas01mj@732: { mas01mj@732: flag = "!"; mas01mj@732: } mas01mj@732: this.socket.writeUTFBytes("define " + flag + " \"" + term + "\"\r\n"); mas01mj@732: this.socket.flush(); mas01mj@732: } mas01mj@732: mas01mj@732: //// Private functions //// mas01mj@732: mas01mj@732: private function connected(event:Event):void mas01mj@732: { mas01mj@732: // Wait to dispatch an event until we get the 220 response. mas01mj@732: } mas01mj@732: mas01mj@732: private function disconnected(event:Event):void mas01mj@732: { mas01mj@732: dispatchEvent(new DisconnectedEvent(DisconnectedEvent.DISCONNECTED)); mas01mj@732: } mas01mj@732: mas01mj@732: private function incomingServerXML(event:ResultEvent):void mas01mj@732: { mas01mj@732: var dictd:Namespace = new Namespace("http://www.luetzschena-stahmeln.de/dictd/"); mas01mj@732: var result:XML = event.result as XML; mas01mj@732: var server:String, description:String; mas01mj@732: var servers:Array = new Array(); mas01mj@732: for each (var serverNode:XML in result.dictd::server) mas01mj@732: { mas01mj@732: server = serverNode.dictd::dictdurl; mas01mj@732: description = serverNode.dictd::description; mas01mj@732: if (StringUtil.trim(server).length != 0 && mas01mj@732: StringUtil.trim(description).length != 0) mas01mj@732: { mas01mj@732: var dServer:DictionaryServer = new DictionaryServer(); mas01mj@732: dServer.server = server.replace("dict://", ""); mas01mj@732: dServer.description = description; mas01mj@732: servers.push(dServer); mas01mj@732: } mas01mj@732: } mas01mj@732: var dEvent:DictionaryServerEvent = new DictionaryServerEvent(DictionaryServerEvent.SERVERS); mas01mj@732: dEvent.servers = servers; mas01mj@732: dispatchEvent(dEvent); mas01mj@732: } mas01mj@732: mas01mj@732: private function incomingData(event:CompleteResponseEvent):void mas01mj@732: { mas01mj@732: var rawResponse:String = event.response; mas01mj@732: var response:Response = this.parseRawResponse(rawResponse); mas01mj@732: var responseCode:uint = response.code; mas01mj@732: if (responseCode == 552) // no matches mas01mj@732: { mas01mj@732: throwNoMatchEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode >= 400 && responseCode <= 599) // error mas01mj@732: { mas01mj@732: throwErrorEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode == 220) // successful connection mas01mj@732: { mas01mj@732: dispatchEvent(new ConnectedEvent(ConnectedEvent.CONNECTED)); mas01mj@732: } mas01mj@732: else if (responseCode == 110) // databases are being returned mas01mj@732: { mas01mj@732: throwDatabasesEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode == 111) // matches strategies mas01mj@732: { mas01mj@732: throwMatchStrategiesEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode == 152) // matches mas01mj@732: { mas01mj@732: throwMatchEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode == 150) mas01mj@732: { mas01mj@732: throwDefinitionHeaderEvent(response); mas01mj@732: } mas01mj@732: else if (responseCode == 151) mas01mj@732: { mas01mj@732: throwDefinitionEvent(response); mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: private function ioError(event:IOErrorEvent):void mas01mj@732: { mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function httpError(event:FaultEvent):void mas01mj@732: { mas01mj@732: trace("httpError!"); mas01mj@732: } mas01mj@732: mas01mj@732: private function securityError(event:SecurityErrorEvent):void mas01mj@732: { mas01mj@732: trace("security error!"); mas01mj@732: trace(event.text); mas01mj@732: } mas01mj@732: mas01mj@732: // Dispatch new events. mas01mj@732: mas01mj@732: private function throwDatabasesEvent(response:Response):void mas01mj@732: { mas01mj@732: var databases:Array = new Array(); mas01mj@732: var responseArray:Array = response.body.split("\r\n"); mas01mj@732: for each (var line:String in responseArray) mas01mj@732: { mas01mj@732: var name:String = line.substring(0, line.indexOf(" ")); mas01mj@732: if (name == "--exit--") mas01mj@732: { mas01mj@732: if (this.dbShortList) mas01mj@732: { mas01mj@732: break; mas01mj@732: } mas01mj@732: continue; mas01mj@732: } mas01mj@732: var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); mas01mj@732: databases.push(new Database(name, description)); mas01mj@732: } mas01mj@732: var event:DatabaseEvent = new DatabaseEvent(DatabaseEvent.DATABASES); mas01mj@732: event.databases = databases; mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwMatchStrategiesEvent(response:Response):void mas01mj@732: { mas01mj@732: var strategies:Array = new Array(); mas01mj@732: var responseArray:Array = response.body.split("\r\n"); mas01mj@732: for each (var line:String in responseArray) mas01mj@732: { mas01mj@732: var name:String = line.substring(0, line.indexOf(" ")); mas01mj@732: var description:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); mas01mj@732: strategies.push(new MatchStrategy(name, description)); mas01mj@732: } mas01mj@732: var event:MatchStrategiesEvent = new MatchStrategiesEvent(MatchStrategiesEvent.MATCH_STRATEGIES); mas01mj@732: event.strategies = strategies; mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwMatchEvent(response:Response):void mas01mj@732: { mas01mj@732: var matches:Array = new Array(); mas01mj@732: var responseArray:Array = response.body.split("\r\n"); mas01mj@732: for each (var line:String in responseArray) mas01mj@732: { mas01mj@732: var match:String = line.substring(line.indexOf(" ")+1, line.length).replace(/\"/g,""); mas01mj@732: matches.push(match); mas01mj@732: } mas01mj@732: var event:MatchEvent = new MatchEvent(MatchEvent.MATCH); mas01mj@732: event.matches = matches; mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwErrorEvent(response:Response):void mas01mj@732: { mas01mj@732: var event:ErrorEvent = new ErrorEvent(ErrorEvent.ERROR); mas01mj@732: event.code = response.code; mas01mj@732: event.message = response.headerText; mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwNoMatchEvent(response:Response):void mas01mj@732: { mas01mj@732: dispatchEvent(new NoMatchEvent(NoMatchEvent.NO_MATCH)); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwDefinitionHeaderEvent(response:Response):void mas01mj@732: { mas01mj@732: var event:DefinitionHeaderEvent = new DefinitionHeaderEvent(DefinitionHeaderEvent.DEFINITION_HEADER); mas01mj@732: event.definitionCount = uint(response.headerText.substring(0, response.headerText.indexOf(" "))); mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function throwDefinitionEvent(response:Response):void mas01mj@732: { mas01mj@732: var event:DefinitionEvent = new DefinitionEvent(DefinitionEvent.DEFINITION); mas01mj@732: var def:Definition = new Definition(); mas01mj@732: var headerText:String = response.headerText; mas01mj@732: var tokens:Array = headerText.match(/"[^"]+"/g); mas01mj@732: def.term = String(tokens[0]).replace(/"/g, ""); mas01mj@732: def.database = String(tokens[1]).replace(/"/g, ""); mas01mj@732: def.definition = response.body; mas01mj@732: event.definition = def; mas01mj@732: dispatchEvent(event); mas01mj@732: } mas01mj@732: mas01mj@732: private function parseRawResponse(rawResponse:String):Response mas01mj@732: { mas01mj@732: var response:Response = new Response(); mas01mj@732: var fullHeader:String; mas01mj@732: if (rawResponse.indexOf("\r\n") != -1) mas01mj@732: { mas01mj@732: fullHeader = rawResponse.substring(0, rawResponse.indexOf("\r\n")); mas01mj@732: } mas01mj@732: else mas01mj@732: { mas01mj@732: fullHeader = rawResponse; mas01mj@732: } mas01mj@732: var responseCodeMatch:Array = fullHeader.match(/^\d{3}/); mas01mj@732: response.code = uint(responseCodeMatch[0]); mas01mj@732: response.headerText = fullHeader.substring(fullHeader.indexOf(" ")+1, fullHeader.length); mas01mj@732: var body:String = rawResponse.substring(rawResponse.indexOf("\r\n")+2, rawResponse.length); mas01mj@732: body = body.replace(/\r\n\.\./, "\r\n."); mas01mj@732: response.body = body; mas01mj@732: return response; mas01mj@732: } mas01mj@732: } mas01mj@732: }