Esta classe tem como objetivo estabelecer comunicação com um servidor IRC, receber e enviar mensagens de acordo com o protocolo IRC e disparar eventos aos listeners conforme o significado das mensagens recebidas.
1. //////////////////////////////////////////////////////////////
// Esta classe tem a responsabilidade de conhecer o protocolo
// IRC - Internet Relay Chat
//
// Comunica com o servidor de Irc e dispara eventos conforme
// o significado das mensagens que recebe.
//
// Autor: José Travado Data: 12/07/22
// versão 2
//////////////////////////////////////////////////////////////
package irc.comunicador
{
import fl.controls.*;
import flash.net.Socket;
import flash.events.*;
import flash.errors.*;
import flash.system.Security;
public class ComunicadorIrc
{
// Para provocar eventos
public var evento:EventDispatcher=new EventDispatcher();
//Socket de comunicação
var s:Socket=new Socket();
//strings com a comunicação
var erro,mensagemCliente,mensagemServidor,resposta:String;
//////////////////////////////////////////////////////////////////////////
//mensagem decomposta
//[0] nome servidor
//[1] utilizador
//[2] host
//[3] comando
// [4 e seguintes] parâmetros
var mensagem:Array;
////////////////////////////////////////////////////////////////////////
//lista de salas
var salas:Array;
var quantidadeSalas:int = 0;
var utilizador:String;
public function ComunicadorIrc()
{
mensagemServidor = "";
mensagem=new Array();
salas=new Array();
//Eventos provocados pela comunicação (Socket).
s.addEventListener(Event.CLOSE, closeHandler);
s.addEventListener(Event.CONNECT, connectHandler);
s.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
s.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}
//Estabelecer comunicação com um servidor de IRC
public function conectarRede(endereco:String,porto:int)
{
Security.allowDomain(endereco);
Security.loadPolicyFile(endereco);
s.connect(endereco,porto);
resposta = endereco + porto;
evento.dispatchEvent(new Event("Mensagem Enviada"));
}
function reconectar()
{
}
// Funções para enviar mensagem
public function desconectar()
{
if (s.connected)
{
1/7
2. enviar("QUIT :Até à próxima");
s.close();
quantidadeSalas = 0;
}
s == null;
}
//Seletores
public function obterListaSalas():Array
{
return salas;
}
public function obterMensagem():String
{
return mensagem[4];
}
public function obterMensagemCompleta():Array
{
return mensagem;
}
public function obterParametro(i:int):String
{
return mensagem[4+i];
}
public function obterErro():String
{
return erro;
}
public function obterNomes(sala:String)
{
if (s.connected)
{
enviar("Names "+sala);
}
}
public function obterLista()
{
if (s.connected)
{
enviar("List ");
}
}
public function obterMensagemDia()
{
if (s.connected)
{
enviar("MOTD ");
}
}
public function obterEstado():Boolean
{
return s.connected;
}
//Modificadores
public function limparMensagem()
{
mensagemServidor = "";
}
public function obterQuantidadeSalas()
{
return quantidadeSalas;
}
//Eventos do socket
function closeHandler(event:Event):void
{
evento.dispatchEvent(new Event("Desconectado"));
}
function connectHandler(event:Event):void
{
2/7
3. evento.dispatchEvent(new Event("Conectado"));
}
function securityErrorHandler(event:SecurityErrorEvent):void
{
trace("securiyErrorHandler: " + event);
erro = event;
evento.dispatchEvent(new Event("Erro"));
}
function ioErrorHandler(event:IOErrorEvent):void
{
trace("IOErro " );
erro = event;
evento.dispatchEvent(new Event("Erro"));
}
function socketDataHandler(event:ProgressEvent):void
{
trace("Dados Recebidos");
receberMensagem();
}
public function registarUtilizador(utilizador:String):void
{
if (utilizador != null)
{
this.utilizador = utilizador;
enviar("NICK "+utilizador);
enviar("USER "+utilizador+" 0 * :"+utilizador);
}
}
//Para enviar mensagens
function enviar(str:String):void
{
prepararMensagem(str);
s.flush();
}
function prepararMensagem(str:String):void
{
str += "rn";
trace(str);
try
{
s.writeMultiByte(str,"iso-8859-1");
}
catch (e:IOError)
{
trace(e);
}
}
private function receberMensagem():void
{
mensagemServidor = s.readMultiByte(s.bytesAvailable,"iso-8859-1");
evento.dispatchEvent(new Event("Mensagem Recebida"));
trace(mensagemServidor);
//O servidor verifica a conexão pingando constantemente
if (mensagemServidor.indexOf("rn") > 0)
{
decomporMensagem();
}
}
//Decomposição de uma mensagem segundo o RFC 2812 ; 1459
function decomporMensagem()
{
var fim:int = obterFimMensagem();
var pos:int = obterFimPrefixo();
pos = verificaEspacos(pos);
pos = obterFimComando(pos);
pos = verificaEspacos(pos);
3/7
4. if (pos != -1 && pos < fim)
{
obterParametros(pos,fim);
//A mensagem terminou, retirá-la da mensagemservidor, tratá-la e decompor o resto
//
//ou deixar que seja completada com outro fluxo de mensagem ???
mensagemServidor = mensagemServidor.substring(fim + 2);
tratarMensagem();
if (mensagemServidor.indexOf("rn") > 0)
{
decomporMensagem();
}
}
else
{
erro = "Mensagem incompleta";
evento.dispatchEvent(new Event("Erro"));
}
}
function verificaEspacos(pos:int):int
{
var i:int;
for (i=pos; i<mensagemServidor.length; i++)
{
if (mensagemServidor.charAt(i) != " ")
{
break;
}
}
return i;
}
function obterFimMensagem()
{
return mensagemServidor.indexOf("rn");
}
//Verifica se a mensagem tem prefixo e decompõem-o
function obterFimPrefixo():int
{
var posUtilizador:int;
var posHost:int;
var valor:int = 0;
if (mensagemServidor.indexOf(":",0) == 0)
{
valor = mensagemServidor.indexOf(" ",0);
posUtilizador = mensagemServidor.indexOf("!",0);
if (posUtilizador < valor)
{
mensagem[0] = mensagemServidor.substring(1,posUtilizador);
posHost = mensagemServidor.indexOf("@",posUtilizador + 1);
if (posHost < valor)
{
mensagem[1] = mensagemServidor.substring(posUtilizador + 1,posHost);
mensagem[2] = mensagemServidor.substring(posHost + 1,valor);
}
else
{
mensagem[1]=mensagemServidor.substring(posUtilizador+1,(valor));
}
}
else
{
mensagem[0] = mensagemServidor.substring(1,valor);
}
}
return (valor);
}
//Obtem o comando
function obterFimComando(pos:int):int
{
var posEspaco:int = mensagemServidor.indexOf(" ",pos);
if (posEspaco != -1)
{
mensagem[3] = mensagemServidor.substring(pos,posEspaco);
}
return posEspaco;
4/7
5. }
function lerQuantidadeSalas(texto:String):int
{
var valor:int = 0;
var pos:int = texto.indexOf(" ",7);
if (pos != -1)
{
var str:String = texto.substring(7,pos);
//if(!isNaN(str))
valor = parseInt(texto);
}
return valor;
}
//obtem o parametro e o trailing se existir
function obterParametros(pos,fim:int)
{
var posicao:int = 5;
var fimMiddle:int;
var posMiddle:int = mensagemServidor.indexOf(" ",pos);
var posParametro:int = mensagemServidor.indexOf(":",pos);
if (posParametro >= pos)
{
mensagem[4] = mensagemServidor.substring(posParametro + 1,fim + 2);
}
else
{
posParametro = fim;
}
while (posMiddle!=-1 && (posMiddle)<posParametro)
{
mensagem[posicao++] = mensagemServidor.substring(pos,posMiddle);
pos=posMiddle+1;
posMiddle = mensagemServidor.indexOf(" ",pos);
//trace("param - "+ mensagem[posicao-1]+" - Fim"+(posicao-1));
}
}
function tratarMensagem()
{
switch (mensagem[3].toString().toUpperCase())
{
case "001" :
case "002" :
case "003" :
case "004" :
evento.dispatchEvent(new Event("Utilizador Aceite"));
break;
case "005" :
reconectar();
evento.dispatchEvent(new Event("Reconecção"));
break;
case "254" :
lerQuantidadeSalas(mensagem[4]);
evento.dispatchEvent(new Event("Obtido Número de Salas"));
break;
case "321" :
evento.dispatchEvent(new Event("Inicio Recepção Salas"));
break;
case "322" :
evento.dispatchEvent(new Event("Recepção Sala"));
break;
case "323" :
evento.dispatchEvent(new Event("Fim Recepção Salas"));
break;//Fim de lista
case "341" :
evento.dispatchEvent(new Event("Convite Enviado"));
break;
case "347" :
evento.dispatchEvent(new Event("Convite efetuado"));
5/7
6. break;
case "349" :
evento.dispatchEvent(new Event("Erro no Convite"));
break;
case "366" :
evento.dispatchEvent(new Event("Fim Recepção Nomes"));
break;
case "376" :
evento.dispatchEvent(new Event("Fim Mensagem do Dia"));
break;
case "403" :
evento.dispatchEvent(new Event("Sala Desconhecida"));
break;
case "406" :
evento.dispatchEvent(new Event("Utilizador Desconhecido"));
break;
case "407" :
case "412" :
case "413" :
case "414" :
case "415" :
evento.dispatchEvent(new Event("Erro no Envio na Conversa"));
break;
case "421" :
evento.dispatchEvent(new Event("Erro Desconhecido"));
break;
case "433" :
case "436" :
case "437" :
case "451" :
evento.dispatchEvent(new Event("Erro de Utilizador"));
break;
case "441" :
case "442" :
evento.dispatchEvent(new Event("Erro de Sala"));
break;
case "464" :
evento.dispatchEvent(new Event("Senha Incorreta"));
break;
case "471" :
case "472" :
case "473" :
case "474" :
case "475" :
case "476" :
case "477" :
case "479" :
case "481" :
evento.dispatchEvent(new Event("Impossível Entrar na Sala"));
break;
case "478" :
evento.dispatchEvent(new Event("Sala Cheia"));
break;
case "PRIVMSG" :
evento.dispatchEvent(new Event("Recepção Conversa"));
break;
case "PING" :
pingar();
break;
default :
}
}
public function entrarSala(sala:String)
{
if (s.connected)
{
enviar("Join "+sala);
}
}
public function conversarCom(texto,utilizador:String)
{
if (s.connected)
{
enviar("PRIVMSG "+ utilizador+ " :" + texto);
6/7
7. }
}
public function abandonarSala(sala:String)
{
if (s.connected)
{
enviar("PART "+sala);
}
}
function pingar()
{
enviar("PONG :"+ mensagem[4]);
}
}
}
7/7