Cliente de IRC (2º Trabalho Laboratorial) FEUP Redes de Computadores MIEIC – 2009/2010 Elementos do Grupo: João Carlos Figueiredo Rodrigues Prudêncio, [email protected] Seraphin Rodrigues Miranda, [email protected] Índice Declaração de Autoria ................................................................................................................... 3 Introdução ..................................................................................................................................... 4 Descrição do Protocolo ................................................................................................................. 5 Arquitectura do Sistema ............................................................................................................... 8 Funcionalidades Adicionais ....................................................................................................... 9 Testes realizados e exemplos de utilização .............................................................................. 9 Conclusão .................................................................................................................................... 11 Bibliografia .................................................................................................................................. 12 Anexo A ....................................................................................................................................... 13 Cliente.c................................................................................................................................... 13 irc.h.......................................................................................................................................... 15 irc.c .......................................................................................................................................... 18 replies.h ................................................................................................................................... 33 replies.c ................................................................................................................................... 39 Preferencias.java ..................................................................................................................... 55 Canal.java ................................................................................................................................ 62 Chat.java.................................................................................................................................. 63 Preferencias.form .................................................................................................................... 88 Chat.form ................................................................................................................................ 95 Página 2 de 104 Declaração de Autoria Declaramos sobre compromisso de honra que este trabalho nas suas partes constituintes e código é original e da nossa autoria, não correspondendo, portanto, a cópia ou tradução de outros trabalhos já realizados, na FEUP ou fora dela. Subscrevemos a declaração acima: João Carlos Figueiredo Rodrigues Prudêncio, Seraphin Rodrigues Miranda. 3 Introdução Este projecto foi realizado no âmbito da unidade curricular Redes de Computadores, do 2º Semestre do 3º Ano do Mestrado Integrado em Engenharia Informática e Computação. O principal objectivo deste trabalho é implementar um cliente IRC. A implementação do cliente foi desenvolvida na linguagem de programação C e a interface gráfica foi desenvolvida na linguagem de programação Java. A implementação do cliente IRC segue o protocolo IRC, restringindo-se ao número de comandos pedidos no enunciado do trabalho. Para além dos comandos pedidos no enunciado, o cliente IRC é capaz enviar todos os comandos que não necessitam de manipulação directa do cliente IRC. Entende-se por manipulação directa, comandos que necessitam de alteração das propriedades associadas à interface gráfica para além daquelas que foram pedidas no enunciado. 4 Descrição do Protocolo O protocolo IRC é um protocolo baseado em comandos em formato de texto. Para efectuar qualquer comunicação entre cliente-servidor é necessário usar sockets, os quais permitirão enviar mensagens com os comandos desejados. As mensagens têm uma sintaxe predefinida e são enviadas para o servidor podendo gerar ou não uma resposta. Esta resposta está associado a um código numérico, que deverá ser interpretado pelo cliente como reply ou error. Cada mensagem pode consistir em três partes: o prefixo (opcional), o comando e os parâmetros (que podem chegar até 15). A presença do prefixo é assinalada pelo carácter ':', que deverá ser o primeiro carácter da mensagem. Para mais detalhes consultar o protocolo. Este cliente IRC implementa os seguintes comandos: HELP Uso: /HELP [<comando>] Explicação: Permite obter ajuda geral sobre o uso do comando HELP ou obter ajuda sobre um comando específico. LIST Uso: /LIST Explicação: Devolve a lista de todos os canais existentes no servidor. JOIN Uso: /JOIN <canal> [<password>]( , <canal> [<password>])* Explicação: Permite o cliente juntar-se a um canal ou a uma lista de canais. Para além da lista de canais pode inserir a password de acesso ao canal se esta existir. PART Uso: /PART <canal> ( , <canal>)* [<Mensagem de saída>] Explicação: Sai de um canal ou de uma lista de canais podendo ainda mandar uma mensagem de saída. QUIT Uso: /QUIT 5 Explicação: Termina a comunicação entre o cliente e o servidor. NICK Uso: /NICK <nick> Explicação: Define o nick com o qual o cliente será identificado. AWAY Uso: /AWAY [<mensagem>] Explicação: Altera o estado para ausente podendo exibir uma mensagem explicativa. Para sair do estado ausente tem que voltar a enviar o comando AWAY sem mensagem. WHOIS Uso: /WHOIS [ <target> ] <mask> *( "," <mask> ) Explicação: Este comando permite obter informações sobre determinado(s) cliente(s) consoante o uso de wildcards nos nicks dos targets. INVITE Uso: /INVITE <nick> <canal> Explicação: Permite enviar um convite a uma determinada pessoa para se juntar a um canal. KICK Uso: /KICK <canal> *( "," <canal> ) <nick> *( "," <nick> ) [<comentario>] Explicação: Expulsa de um canal ou de vários canais, um ou vários utilizadores podendo ainda associar a expulsão a uma mensagem personalizada. TOPIC Uso: /TOPIC <canal> Explicação: Devolve o tópico do canal em consulta. MSG Uso: /MSG (<nick_destinatario> | <canal>) <texto> Explicação: Permite mandar uma mensagem para um canal ou para uma determinada pessoa. QUERY Uso: /QUERY <nick> Explicação: Se a pessoa em questão e o cliente usarem o query entre eles, então eles poderão usar o canal para comunicar sem que os outros utilizadores do canal consigam ver as mensagens trocadas. NOTICE Uso: /NOTICE (<nick_destinatario> | <canal>) <texto> Explicação: Semelhante ao comando MSG, difere nas respostas enviadas pelo servidor que não será visualizada na janela onde aparecerá esta mensagem. NOTIFY Uso: /NOTIFY <nick> Explicação: Devolve uma mensagem quando a pessoa em questão se ligar a um canal que está a ser utilizado pelo cliente. IGNORE Uso: /IGNORE <nick> 6 Explicação: Todas as mensagens recebidas com este nick são desprezadas. PONG Uso: /PONG <host> Explicação: Resposta de um pedido de ping com o host do ping. PASS Uso: /PASS <password> Explicação: Password associado ao nick. USER Uso: /USER <nick> <mode> <unused> : <nome_real> Explicação: Permite efectuar a autentificação/login do utilizador. 7 Arquitectura do Sistema O sistema foi dividido em 2 módulos, que correspondem ao módulo do cliente e ao módulo da interface gráfica. O cliente IRC é constituído basicamente por duas threads. Uma thread para a leitura dos dados provenientes do servidor IRC e outra thread para a leitura dos dados provenientes da interface gráfica. Consoante os resultados dos parsings são efectuados as operações necessárias para a obtenção e reencaminhamento das respostas. O fluxo de dados pode ser observado na seguinte imagem: Imagem 1- Fluxo de dados do sistema. Imagem 1 - Fluxo de dados do sistema A escolha do tipo de ligação entre o Servidor IRC e o Cliente IRC foi efectuada com base no protocolo existente, mais concretamente usando um socket com conexão TCP/IP associada por defeito ao porto número 6667. Relativamente à ligação entre o Cliente IRC e a interface gráfica, decidimos usar, também, um socket com conexão TCP/IP. Esta escolha foi baseada nas características do TCP/IP onde privilegiamos a qualidade da transmissão tentando evitar a recepção de pacotes de forma desordenada e evitando a recepção de pacotes duplicados. Esta escolha também foi baseada no facto do que a interface só seria utilizada numa ligação do tipo unicast. 8 Funcionalidades Adicionais No que diz respeito às funcionalidades adicionais foi desenvolvido uma interface gráfica na linguagem de programação Java. Para tal usou-se a biblioteca Swing do java para desenvolver um ambiente para interagir com o servidor IRC. Para interagir com o programa desenvolvido na linguagem C, efectuamos uma ligação por TCP/IP para a troca de dados. Em relação aos comandos adicionais foram implementados todos os comandos sugeridos no enunciado a excepção do comando /ME que não nos foi possível implementar por falta de documentação. Os comandos já foram explicados no capítulo da Descrição do Protocolo. Para além destas funcionalidades adicionais simplificamos a utilização do Cliente IRC e da Interface Gráfica. Para isso fizemos com que a Interface Gráfica fosse aberta ao mesmo tempo usando uma função para efectuar chamadas ao sistema operativo. Deste modo evitamos problemas e complicações inerentes ao uso de batch files ou scripts. Testes realizados e exemplos de utilização 9 Para testar a aplicação, usou-se o servidor irc.ptnet.org. Foram testados todos os comandos explicados acima. Além disso, é possível também abrir novas janelas quando existem conversas num canal, ou com uma pessoa. Também é possível mudar o estado através de um botão. Para fechar janelas basta carregar no botão no com uma cruz vermelha localizada na parte superior. Imagem 2 - Ilustração da Interface Gráfica 10 Conclusão Concluindo, acreditamos que este trabalho foi necessário para a concretização dos conceitos inerentes aos protocolos de ligação de rede, nomeadamente o protocolo TCP/IP. Todo o nosso trabalho cumpre com as especificações detalhadas no enunciado do projecto e ainda segue as especificidades associadas ao protocolo IRC. Para além das especificações básicas cumpre as especificações adicionais, ditas de especificações de valorização. Finalmente, todo o nosso árduo trabalho culmina nesta aplicação na qual depositamos a nossa total confiança. 11 Bibliografia Protocolo IRC utilizado - http://irchelp.org/irchelp/rfc/rfc2812.txt Slides da unidade curricular de Redes de Computadores http://paginas.fe.up.pt/~jruela/redes/rc_mieic_index.html 12 Anexo A Cliente.c #include "irc.h" //Var globais int flagRead = 1; int flagWhile = 1; int initThread = 0; int main(int argc, char** argv){ if(fork() == 0) { //Abertura do GUI usleep(1000); char *cmd[] ={ "java", "-jar" ,"interface.jar", (char* )0 }; execv("/usr/bin/java", cmd); exit(0); } else { if(argc == 2) ligarSocket(atoi(argv[1])); else ligarSocket(6001); 13 } //Ciclo de leitura de comandos char buf[MSG_SIZE]; while(1){ recvfrom(so, buf, sizeof(buf), 0, (struct sockaddr*)&client_addr, &size_client_addr); printf("%s\n",buf); strcat(buf, "\n"); parseGUI(buf); if(strcmp(buf, "\n")!=0 && strcmp(buf, "quit\n")!=0) writeToSocket(sockfd, buf); memset(buf, 0, MSG_SIZE); } return 0; } 14 irc.h #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <resolv.h> #include <sys/signal.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdarg.h> #include <sched.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <netdb.h> #include <string.h> #include <pthread.h> #include <ctype.h> #include <unistd.h> #include "replies.h" #define MSG_SIZE 2048 #define port_interface 6001 //Var definidas no cliente.c extern int flagRead; extern int flagWhile; 15 extern int initThread; //Var para a ligacao ao GUI int so,size_addr,srv,size_client_addr; struct sockaddr_in addr; struct sockaddr_in client_addr; //Socket para ligar ao servidor IRC int sockfd; //Buffer com dados lidos do servidor char readBuffer[MSG_SIZE]; //Thread de leitura que escreve no buffer readBuffer pthread_t threadRead; //Funcao que escreve uma menssagem num determinado socket int writeToSocket(int sock, char * msg); //Funcao parser para a menssagem PING char * ping(char * msg); //Funcao de parser para a menssagem de grupo char * Group(char * msg); //Parser geral void parserF(char * msg); //Funcao auxiliar para o parser de espacos char * auxBetweenSpaces(char * msg); 16 //Funcao que le a partir do socket e escreve no readBuffer o que leu void * readFromSocket(); //Inicializacao da conexao : PASS-NICK-USER void initConnection(char * nick, char * password); //Parser para o GUI void parseGUI(char * msg); //Inicializacao do socket para o servidor void socketCli(char * ip, char * port); //Inicializacao do socket para o GUI void ligarSocket(int porta); 17 irc.c #include "irc.h" #include "replies.h" int writeToSocket(int sock, char * msg){ int bytes = 0; if(strcmp(msg, "") != 0){ bytes = write(sock, msg, strlen(msg)); } return bytes; } char * ping(char * msg){ int i =0; for(; i < strlen(msg) - 5; i++) { if(msg[i] == 'P' && msg[i+1] == 'I' && msg[i+2] == 'N' && msg[i+3] == 'G' && msg[i+4] == ' ' && msg[i+5] == ':') { int j = i+6; int k=0; char * strAux = (char*) malloc((strlen(msg)-j+1) * sizeof(char)); while(j < strlen(msg) && msg[j] != '\n' && msg[j] != ' '){ strAux[k] = msg[j]; k++; j++; } 18 return strAux; } } return NULL; } char * Group(char * msg){ int i =0; for(; i < strlen(msg); i++) { if(msg[i] == '=') { int k=0; int j = i; char * strAux = (char*) malloc((strlen(msg)-j+1) * sizeof(char)); for(; j < strlen(msg) ; j++) { if(msg[j] == ':') { j++; while(j < strlen(msg) && msg[j] != '\n'){ strAux[k] = msg[j]; j++; k++; } return strAux; } } 19 } } return NULL; } void parserF(char * msg){ char * str = (char*) malloc(MSG_SIZE * sizeof(char)); strcpy(str, msg); char * str2 = (char*) malloc(MSG_SIZE * sizeof(char)); strcpy(str2, msg); char * auxStr = strstr(msg, "PRIVMSG"); if(auxStr != NULL) { char * tempRes = strstr(auxStr, "#"); if(tempRes != NULL){ //Private message GRUPO char * parsAux = strtok(str, ":"); char * parsAux2 = strtok(parsAux, "!"); strtok(auxStr, "#"); char * parsAux4 = strtok(NULL, " "); char * parsAux5 = strtok(NULL, ":"); char * parsAux6 = strtok(parsAux5, "\n\r"); char * final = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final,"GMSG-%s-#%s-%s", parsAux2, parsAux4, parsAux6); 20 printf("%s\n", final); writeToSocket(so, final); } else { //Private message One char * pars1 = strtok(str2, ":"); char * pars2 = strtok(pars1, "!"); strtok(str, ":"); char * parsAux2 = strtok(NULL, ":"); char * parsAux3 = strtok(parsAux2, "\n\r"); strtok(str, " "); strtok(NULL, " "); strtok(NULL, " "); char * final = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final,"PMSG-%s-%s", pars2, parsAux3); printf("%s\n", final); writeToSocket(so, final); } } else { auxStr = strstr(msg, "PART"); if(auxStr != NULL) 21 { //Saiu alguem char * parsAux = strtok(str, ":"); char * parsAux2 = strtok(parsAux, "!"); strtok(str2, " "); strtok(NULL, " "); char * parsAux3 = strtok(NULL, " "); char * final = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final,"PART-%s-%s", parsAux2, parsAux3); printf("%s\n", final); writeToSocket(so, final); } else { auxStr = strstr(msg, "JOIN"); if(auxStr != NULL) { //pessoa entrou char * parsAux = strtok(str, ":"); char * parsAux2 = strtok(parsAux, "!"); strtok(str2, ":"); char * parsAux4 = strtok(NULL, ":"); char * parsAux5 = strtok(parsAux4, "\n\r"); 22 char * final = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final,"JOIN-%s-%s", parsAux2, parsAux5); printf("%s\n", final); writeToSocket(so, final); char * final2 = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final2,"GROUP %s", Group(msg)); printf("%s\n", final2); writeToSocket(so, final2); } else { auxStr = strstr(msg, "PING"); if(auxStr != NULL) { char * final = (char*) malloc(MSG_SIZE * sizeof(char)); sprintf(final,"PONG %s\n", ping(msg)); printf("%s\n", final); writeToSocket(sockfd, final); } else{ writeToSocket(so, msg); } } } } 23 } char * auxBetweenSpaces(char * msg){ int i = 0, j=0; char * auxBuff=(char*)malloc(MSG_SIZE*sizeof(char)); for(; i< strlen(msg); i++) { if(msg[i] == ' ') { int k =0; for(j = i+1; j < strlen(msg); j++) { if(msg[j] != '\n' && msg[j] != ' '); { auxBuff[k] = msg[j]; k++; } if(msg[j] == ' ') { //printf("!!%s!!\n", auxBuff); return auxBuff; } } } } return NULL; 24 } void * readFromSocket(){ int bytes = 0; while(flagWhile == 1){ if(flagRead == 1){ bytes = read(sockfd, readBuffer, MSG_SIZE); printf("\n%s\n", readBuffer); char * auxStr=(char*)malloc(MSG_SIZE*sizeof(char)); auxStr = strstr(readBuffer, "WHOIS"); if(auxStr != NULL) { writeToSocket(so, readBuffer); } char * auxBuf=(char*)malloc(MSG_SIZE*sizeof(char)); strcpy(auxBuf,readBuffer); //parserF(readBuffer); char ** res = (char**) malloc(MSG_SIZE * sizeof(char*) *sizeof(char)); char *result = (char*)malloc(MSG_SIZE*sizeof(char)); result = strtok( auxBuf, "\n" ); int i = 0; 25 while( result != NULL ) { if(auxBetweenSpaces(result) != NULL) { char * auxTmp=(char*)malloc(MSG_SIZE*sizeof(char)); strcpy(auxTmp,result); res[i] = auxBetweenSpaces(auxTmp); char * final=(char*)malloc(MSG_SIZE*sizeof(char)*sizeof(char)); if(atoi(res[i]) >= 400) sprintf(final,"ERRO %s", getResposta(atoi(res[i]))); else sprintf(final,"REPLY %s", getResposta(atoi(res[i]))); if(getResposta(atoi(res[i])) != NULL) writeToSocket(so, final); else parserF(readBuffer); //printf("Res[%d]=%s -> %s!\n", i, res[i], final); i++; } memset(result, 0, MSG_SIZE); result = strtok( auxBuf, "\n" ); } memset(res, 0, MSG_SIZE* sizeof(char*) *sizeof(char)); memset(readBuffer, 0, MSG_SIZE); } 26 } pthread_exit(NULL); } void initConnection(char * nick, char * password){ char bufi[MSG_SIZE]; if(password != NULL){ sprintf(bufi,"PASS %s\n", password); writeToSocket(sockfd, bufi); memset(bufi, 0, MSG_SIZE); } sprintf(bufi,"NICK %s\n", nick); writeToSocket(sockfd, bufi); memset(bufi, 0, MSG_SIZE); sprintf(bufi,"USER %s %s %s :%s \n", nick, "0", "*", "xpto"); writeToSocket(sockfd, bufi); memset(bufi, 0, MSG_SIZE); } void parseGUI(char * msg){ char * str = (char*) malloc(MSG_SIZE * sizeof(char)); strcpy(str, msg); 27 char * auxStr = strstr(msg, "INIT"); if(auxStr != NULL) { char ** res = (char**) malloc(MSG_SIZE * sizeof(char*)); char *result = NULL; result = strtok( str, " " ); int i = 0; while( result != NULL ) { //printf("%dPARSE: %s!\n", i, result); res[i] = result; result = strtok( NULL, " " ); i++; } //printf("STRLEN: %d!", strlen(res)/sizeof(char*)); if((strlen(res)/sizeof(char*)) == 2){ // = 2 //printf("INIT-> !%s!%s!", res[0], res[1]); if(initThread == 0) pthread_create(&threadRead,NULL,readFromSocket, NULL); initThread = 1; initConnection(res[1], NULL); // 1 } else 28 if((strlen(res)/ sizeof(char*) )== 3){ // = 3 //printf("INIT-> !%s!%s!%s!", res[0], res[1], res[2]); if(initThread == 0) pthread_create(&threadRead,NULL,readFromSocket, NULL); initThread = 1; initConnection(res[1], res[2]); // 1 e 2 } } else { auxStr = strstr(msg, "EXIT"); if(auxStr != NULL){ printf("\nEXIT IRC"); //flagWhile = 0; //pthread_exit(NULL); close(sockfd); close(so); exit(0); } else { auxStr = strstr(msg, "IP"); if(auxStr != NULL){ close(sockfd); flagRead = 1; char ** res = (char**) malloc(MSG_SIZE * sizeof(char*)); 29 char *result = NULL; result = strtok( str, " " ); int i = 0; while( result != NULL ) { //printf("%dPARSE: %s!\n", i, result); res[i] = result; result = strtok( NULL, " " ); i++; } //printf("STRLEN: %d!", strlen(res)/sizeof(char*)); if((strlen(res)/sizeof(char*)) == 2){ // = 2 //printf("IP-> !%s!%s!", res[0], res[1]); socketCli(res[1], NULL); // 1 } else if((strlen(res)/ sizeof(char*) )== 3){ // = 3 //printf("IP-> !%s!%s!%s!", res[0], res[1], res[2]); socketCli(res[1], res[2]); // 1 e 2 } } } auxStr = strstr(msg, "quit"); if(auxStr != NULL){ flagRead=0; } 30 } } void socketCli(char * ip, char * port){ if(ip == NULL){ ip = (char*)malloc(15*sizeof(char)); ip = "193.137.208.208"; } if(port==NULL) { port = (char*)malloc(4*sizeof(char)); port = "6667"; } struct sockaddr_in server_addr; /*server address handling*/ bzero((char*)&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(ip); ordered*/ /*32 bit Internet address network byte server_addr.sin_port = htons(atoi(port)); network byte ordered */ /*server TCP port must be /*open an TCP socket*/ if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { 31 perror("socket()"); exit(-1); } /*connect to the server*/ if(connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0){ perror("connect()"); exit(-1); } } void ligarSocket(int porta){ size_addr=sizeof(addr); if ((srv = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket()"); exit(-1); } addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port=htons(porta); bind(srv,(struct sockaddr*)&addr,sizeof(addr)); listen(srv,5); size_client_addr=sizeof(client_addr); so=accept(srv,(struct sockaddr*)&client_addr,&size_client_addr); } 32 replies.h #include <stdlib.h> #include <stdio.h> #define RPL_WELCOME 1 #define RPL_YOURHOST 2 #define RPL_CREATED 3 #define RPL_MYINFO 4 #define RPL_BOUNCE 5 #define RPL_TRACELINK 200 #define RPL_TRACECONNECTING 201 #define RPL_TRACEHANDSHAKE 202 #define RPL_TRACEUNKNOWN 203 #define RPL_TRACEOPERATOR 204 #define RPL_TRACEUSER 205 #define RPL_TRACESERVER 206 #define RPL_TRACESERVICE 207 #define RPL_TRACENEWTYPE 208 #define RPL_TRACECLASS 209 #define RPL_TRACERECONNECT 210 #define RPL_STATSLINKINFO 211 #define RPL_STATSCOMMANDS 212 #define RPL_ENDOFSTATS 219 #define RPL_UMODEIS 221 #define RPL_SERVLIST 234 #define RPL_SERVLISTEND 235 33 #define RPL_STATSUPTIME 242 #define RPL_STATSOLINE 243 #define RPL_LUSERCLIENT 251 #define RPL_LUSEROP 252 #define RPL_LUSERUNKNOWN 253 #define RPL_LUSERCHANNELS 254 #define RPL_LUSERME 255 #define RPL_ADMINME 256 #define RPL_ADMINLOC1 257 #define RPL_ADMINLOC2 258 #define RPL_ADMINEMAIL 259 #define RPL_TRACELOG 261 #define RPL_TRACEEND 262 #define RPL_TRYAGAIN 263 #define RPL_AWAY 301 #define RPL_USERHOST 302 #define RPL_ISON 303 #define RPL_UNAWAY 305 #define RPL_NOWAWAY 306 #define RPL_WHOISUSER 311 #define RPL_WHOISSERVER 312 #define RPL_WHOISOPERATOR 313 #define RPL_WHOWASUSER 314 #define RPL_ENDOFWHO 315 #define RPL_WHOISIDLE 317 #define RPL_ENDOFWHOIS 318 #define RPL_WHOISCHANNELS 319 34 #define RPL_LISTSTART 321 #define RPL_LIST 322 #define RPL_LISTEND 323 #define RPL_CHANNELMODEIS 324 #define RPL_UNIQOPIS 325 #define RPL_NOTOPIC 331 #define RPL_TOPIC 332 #define RPL_INVITING 341 #define RPL_SUMMONING 342 #define RPL_INVITELIST 346 #define RPL_ENDOFINVITELIST 347 #define RPL_EXCEPTLIST 348 #define RPL_ENDOFEXCEPTLIST 349 #define RPL_VERSION 351 #define RPL_WHOREPLY 352 #define RPL_NAMREPLY 353 #define RPL_LINKS 364 #define RPL_ENDOFLINKS 365 #define RPL_ENDOFNAMES 366 #define RPL_BANLIST 367 #define RPL_ENDOFBANLIST 368 #define RPL_ENDOFWHOWAS 369 #define RPL_INFO 371 #define RPL_MOTD 372 #define RPL_ENDOFINFO 374 #define RPL_MOTDSTART 375 #define RPL_ENDOFMOTD 376 35 #define RPL_YOUREOPER 381 #define RPL_REHASHING 382 #define RPL_YOURESERVICE 383 #define RPL_TIME 391 #define RPL_USERSSTART 392 #define RPL_USERS 393 #define RPL_ENDOFUSERS 394 #define RPL_NOUSERS 395 #define ERR_NOSUCHNICK 401 #define ERR_NOSUCHSERVER 402 #define ERR_NOSUCHCHANNEL 403 #define ERR_CANNOTSENDTOCHAN 404 #define ERR_TOOMANYCHANNELS 405 #define ERR_WASNOSUCHNICK 406 #define ERR_TOOMANYTARGETS 407 #define ERR_NOSUCHSERVICE 408 #define ERR_NOORIGIN 409 #define ERR_NORECIPIENT 411 #define ERR_NOTEXTTOSEND 412 #define ERR_NOTOPLEVEL 413 #define ERR_WILDTOPLEVEL 414 #define ERR_BADMASK 415 #define ERR_UNKNOWNCOMMAND 421 #define ERR_NOMOTD 422 #define ERR_NOADMININFO 423 #define ERR_FILEERROR 424 #define ERR_NONICKNAMEGIVEN 431 36 #define ERR_ERRONEUSNICKNAME 432 #define ERR_NICKNAMEINUSE 433 #define ERR_NICKCOLLISION 436 #define ERR_UNAVAILRESOURCE 437 #define ERR_USERNOTINCHANNEL 441 #define ERR_NOTONCHANNEL 442 #define ERR_USERONCHANNEL 443 #define ERR_NOLOGIN 444 #define ERR_SUMMONDISABLED 445 #define ERR_USERSDISABLED 446 #define ERR_NOTREGISTERED 451 #define ERR_NEEDMOREPARAMS 461 #define ERR_ALREADYREGISTRED 462 #define ERR_NOPERMFORHOST 463 #define ERR_PASSWDMISMATCH 464 #define ERR_YOUREBANNEDCREEP 465 #define ERR_YOUWILLBEBANNED 466 #define ERR_KEYSET 467 #define ERR_CHANNELISFULL 471 #define ERR_UNKNOWNMODE 472 #define ERR_INVITEONLYCHAN 473 #define ERR_BANNEDFROMCHAN 474 #define ERR_BADCHANNELKEY 475 #define ERR_BADCHANMASK 476 #define ERR_NOCHANMODES 477 #define ERR_BANLISTFULL 478 #define ERR_NOPRIVILEGES 481 37 #define ERR_CHANOPRIVSNEEDED 482 #define ERR_CANTKILLSERVER 483 #define ERR_RESTRICTED 484 #define ERR_UNIQOPPRIVSNEEDED 485 #define ERR_NOOPERHOST 491 #define ERR_UMODEUNKNOWNFLAG 501 #define ERR_USERSDONTMATCH 502 //Funcao que imprime o erro consoante o inteiro associado char * getResposta(int resposta); 38 replies.c #include "replies.h" //Funcao que imprime o erro consoante o inteiro associado char * getResposta(int resposta){ switch(resposta){ case RPL_WELCOME: return "Welcome to the Internet Relay Network <nick>!<user>@<host>"; break; case RPL_YOURHOST: return "Your host is <servername>, running version <ver>"; break; case RPL_CREATED: return "This server was created <date>"; break; case RPL_MYINFO: return "<servername> <version> <available user modes> <available channel modes>"; break; case RPL_BOUNCE: return "Try server <server name>, port <port number>"; break; case RPL_TRACELINK: return "Link <version & debug level> <destination> <next server> V<protocol version> <link uptime in seconds> <backstreamsendq> <upstream sendq>"; break; 39 case RPL_TRACECONNECTING: return "Try. <class> <server>"; break; case RPL_TRACEHANDSHAKE: return "H.S. <class> <server>"; break; case RPL_TRACEUNKNOWN: return "???? <class> [<client IP address in dot form>]"; break; case RPL_TRACEOPERATOR: return "Oper <class> <nick>"; break; case RPL_TRACEUSER: return "User <class> <nick>"; break; case RPL_TRACESERVER: return "Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> V<protocol version>"; break; case RPL_TRACESERVICE: return "Service <class> <name> <type> <active type>"; break; case RPL_TRACENEWTYPE: return "<newtype> 0 <client name>"; break; case RPL_TRACECLASS: return "Class <class> <count>"; break; 40 case RPL_TRACERECONNECT: return "Unused."; break; case RPL_STATSLINKINFO: return "<linkname> <sendq> <sent messages> <sent Kbytes> <received messages> <received Kbytes> <time open>"; break; case RPL_STATSCOMMANDS: return "<command> <count> <byte count> <remote count>"; break; case RPL_ENDOFSTATS: return "<stats letter> :End of STATS report"; break; case RPL_UMODEIS: return "<user mode string>"; break; case RPL_SERVLIST: return "<name> <server> <mask> <type> <hopcount> <info>"; break; case RPL_SERVLISTEND: return "<mask> <type> :End of service listing"; break; case RPL_STATSUPTIME: return ":Server Up ... days"; // %d days %d:%02d:%02d"; break; case RPL_STATSOLINE: return "O <hostmask> * <name>"; break; 41 case RPL_LUSERCLIENT: return ":There are <integer> users and <integer> services on <integer> servers"; break; case RPL_LUSEROP: return "<integer> :operator(s online"; break; case RPL_LUSERUNKNOWN: return "<integer> :unknown connection(s"; break; case RPL_LUSERCHANNELS: return "<integer> :channels formed"; break; case RPL_LUSERME: return ":I have <integer> clients and <integer> servers"; break; case RPL_ADMINME: return "<server> :Administrative info"; break; case RPL_ADMINLOC1: return ":<admin info>"; break; case RPL_ADMINLOC2: return ":<admin info>"; break; case RPL_ADMINEMAIL: return ":<admin info>"; break; 42 case RPL_TRACELOG: return "File <logfile> <debug level>"; break; case RPL_TRACEEND: return "<server name> <version & debug level> :End of TRACE"; break; case RPL_TRYAGAIN: return "<command> :Please wait a while and try again."; break; case RPL_AWAY: return "<nick> :<away message>"; break; case RPL_USERHOST: return ":*1<reply> *( " " <reply> "; break; case RPL_ISON: return ":*1<nick> *( " " <nick> "; break; case RPL_UNAWAY: return ":You are no longer marked as being away"; break; case RPL_NOWAWAY: return ":You have been marked as being away"; break; case RPL_WHOISUSER: return "<nick> <user> <host> * :<real name>"; break; 43 case RPL_WHOISSERVER: return "<nick> <server> :<server info>"; break; case RPL_WHOISOPERATOR: return "<nick> :is an IRC operator"; break; case RPL_WHOWASUSER: return "<nick> <user> <host> * :<real name>"; break; case RPL_ENDOFWHO: return "<name> :End of WHO list"; break; case RPL_WHOISIDLE: return "<nick> <integer> :seconds idle"; break; case RPL_ENDOFWHOIS: return "<nick> :End of WHOIS list"; break; case RPL_WHOISCHANNELS: return "<nick> :*( ( '@' / '+' <channel> " " "; break; case RPL_LISTSTART: return "Obsolete."; break; case RPL_LIST: return "<channel> <# visible> :<topic>"; break; 44 case RPL_LISTEND: return ":End of LIST"; break; case RPL_CHANNELMODEIS: return "<channel> <mode> <mode params>"; break; case RPL_UNIQOPIS: return "<channel> <nickname>"; break; case RPL_NOTOPIC: return "<channel> :No topic is set"; break; case RPL_TOPIC: return "<channel> :<topic>"; break; case RPL_INVITING: return "<channel> <nick>"; break; case RPL_SUMMONING: return "<user> :Summoning user to IRC"; break; case RPL_INVITELIST: return "<channel> <invitemask>"; break; case RPL_ENDOFINVITELIST: return "<channel> :End of channel invite list"; break; 45 case RPL_EXCEPTLIST: return "<channel> <exceptionmask>"; break; case RPL_ENDOFEXCEPTLIST: return "<channel> :End of channel exception list"; break; case RPL_VERSION: return "<version>.<debuglevel> <server> :<comments>"; break; case RPL_WHOREPLY: return "<channel> <user> <host> <server> <nick> ( 'H' / 'G' > ['*'][ ( '@' / '+' ] :<hopcount> <real name>"; break; case RPL_NAMREPLY: return " ( '=' / '*' / '@' <channel> :[ '@' / '+' ] <nick> *( " " ['@' / '+' ] <nick> "; break; case RPL_LINKS: return "<mask> <server> :<hopcount> <server info>"; break; case RPL_ENDOFLINKS: return "<mask> :End of LINKS list"; break; case RPL_ENDOFNAMES: return "<channel> :End of NAMES list"; break; case RPL_BANLIST: return "<channel> <banmask>"; break; 46 case RPL_ENDOFBANLIST: return "<channel> :End of channel ban list"; break; case RPL_ENDOFWHOWAS: return "<nick> :End of WHOWAS"; break; case RPL_INFO: return ":<string>"; break; case RPL_MOTD: return ":- <text>"; break; case RPL_ENDOFINFO: return ":End of INFO list"; break; case RPL_MOTDSTART: return ":- <server> Message of the day - "; break; case RPL_ENDOFMOTD: return ":End of MOTD command"; break; case RPL_YOUREOPER: return ":You are now an IRC operator"; break; case RPL_REHASHING: return "<config file> :Rehashing"; break; 47 case RPL_YOURESERVICE: return "You are service <servicename>"; break; case RPL_TIME: return "<server> :<string showing server's local time>"; break; case RPL_USERSSTART: return ":UserID Terminal Host"; break; case RPL_USERS: return ":<username> <ttyline> <hostname>"; break; case RPL_ENDOFUSERS: return ":End of users"; break; case RPL_NOUSERS: return ":Nobody logged in"; break; case ERR_NOSUCHNICK: return "<nickname> :No such nick/channel"; break; case ERR_NOSUCHSERVER: return "<server name> :No such server"; break; case ERR_NOSUCHCHANNEL: return "<channel name> :No such channel"; 48 break; case ERR_CANNOTSENDTOCHAN: return "<channel name> :Cannot send to channel"; break; case ERR_TOOMANYCHANNELS: return "<channel name> :You have joined too many channels"; break; case ERR_WASNOSUCHNICK: return "<nickname> :There was no such nickname"; break; case ERR_TOOMANYTARGETS: return "<target> :<error code> recipients. <abort message>"; break; case ERR_NOSUCHSERVICE: return "<service name> :No such service"; break; case ERR_NOORIGIN: return ":No origin specified"; break; case ERR_NORECIPIENT : return ":No recipient given (<command>"; break; case ERR_NOTEXTTOSEND: return ":No text to send"; break; case ERR_NOTOPLEVEL: return "<mask> :No toplevel domain specified"; 49 break; case ERR_WILDTOPLEVEL: return "<mask> :Wildcard in toplevel domain"; break; case ERR_BADMASK: return "<mask> :Bad Server/host mask"; break; case ERR_UNKNOWNCOMMAND: return "<command> :Unknown command"; break; case ERR_NOMOTD: return ":MOTD File is missing"; break; case ERR_NOADMININFO: return "<server> :No administrative info available"; break; case ERR_FILEERROR: return ":File error doing <file op> on <file>"; break; case ERR_NONICKNAMEGIVEN: return ":No nickname given"; break; case ERR_ERRONEUSNICKNAME: return "<nick> :Erroneous nickname"; break; case ERR_NICKNAMEINUSE: return "<nick> :Nickname is already in use"; 50 break; case ERR_NICKCOLLISION: return "<nick> :Nickname collision KILL from <user>@<host>"; break; case ERR_UNAVAILRESOURCE: return "<nick/channel> :Nick/channel is temporarily unavailable"; break; case ERR_USERNOTINCHANNEL: return "<nick> <channel> :They aren't on that channel"; break; case ERR_NOTONCHANNEL: return "<channel> :You're not on that channel"; break; case ERR_USERONCHANNEL: return "<user> <channel> :is already on channel"; break; case ERR_NOLOGIN: return "<user> :User not logged in"; break; case ERR_SUMMONDISABLED: return ":SUMMON has been disabled"; break; case ERR_USERSDISABLED: return ":USERS has been disabled"; break; case ERR_NOTREGISTERED: return ":You have not registered"; 51 break; case ERR_NEEDMOREPARAMS: return "<command> :Not enough parameters"; break; case ERR_ALREADYREGISTRED: return ":Unauthorized command (already registered"; break; case ERR_NOPERMFORHOST: return ":Your host isn't among the privileged"; break; case ERR_PASSWDMISMATCH: return ":Password incorrect"; break; case ERR_YOUREBANNEDCREEP: return ":You are banned from this server"; break; case ERR_KEYSET: return "<channel> :Channel key already set"; break; case ERR_CHANNELISFULL: return "<channel> :Cannot join channel (+l"; break; case ERR_UNKNOWNMODE: return "<char> :is unknown mode char to me for <channel>"; break; case ERR_INVITEONLYCHAN: return "<channel> :Cannot join channel (+i"; 52 break; case ERR_BANNEDFROMCHAN: return "<channel> :Cannot join channel (+b"; break; case ERR_BADCHANNELKEY: return "<channel> :Cannot join channel (+k"; break; case ERR_BADCHANMASK: return "<channel> :Bad Channel Mask"; break; case ERR_NOCHANMODES: return "<channel> :Channel doesn't support modes"; break; case ERR_BANLISTFULL: return "<channel> <char> :Channel list is full"; break; case ERR_NOPRIVILEGES: return ":Permission Denied- You're not an IRC operator"; break; case ERR_CHANOPRIVSNEEDED: return "<channel> :You're not channel operator"; break; case ERR_CANTKILLSERVER: return ":You can't kill a server!"; break; case ERR_RESTRICTED: return ":Your connection is restricted!"; 53 break; case ERR_UNIQOPPRIVSNEEDED: return ":You're not the original channel operator"; break; case ERR_NOOPERHOST: return ":No O-lines for your host"; break; case ERR_UMODEUNKNOWNFLAG: return ":Unknown MODE flag"; break; case ERR_USERSDONTMATCH: return ":Cannot change mode for other users"; break; default: return NULL; } } 54 Preferencias.java public class Preferencias extends javax.swing.JFrame { public Chat chat; /** Creates new form Preferencias */ public Preferencias(Chat c) { chat=c; initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GENBEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jTextField1 = new javax.swing.JTextField(); jTextField2 = new javax.swing.JTextField(); jTextField3 = new javax.swing.JTextField(); jLabel4 = new javax.swing.JLabel(); jTextField4 = new javax.swing.JTextField(); 55 jLabel5 = new javax.swing.JLabel(); jPasswordField1 = new javax.swing.JPasswordField(); jButton1 = new javax.swing.JButton(); jLabel6 = new javax.swing.JLabel(); jTextField5 = new javax.swing.JTextField(); setTitle("Preferências"); jLabel1.setText("Nickname:"); jLabel2.setText("Servidor IRC:"); jLabel3.setText("Porta:"); jTextField1.setText("193.137.208.208"); jTextField2.setText("6001"); jTextField3.setText("localhost"); jLabel4.setText("Servidor: "); jTextField4.setText("prudiperv"); jLabel5.setText("Password:"); jPasswordField1.setText("admin"); 56 jButton1.setText("Confirmar"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jLabel6.setText("Porta IRC:"); jTextField5.setText("6667"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jButton1)) .addGroup(layout.createSequentialGroup() .addGap(28, 28, 28) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel5) .addComponent(jLabel2) 57 .addComponent(jLabel6) .addComponent(jLabel4) .addComponent(jLabel3) .addComponent(jLabel1)) .addGap(33, 33, 33) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTextField4, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE) .addComponent(jTextField2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE) .addComponent(jTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE) .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE) .addComponent(jPasswordField1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE) .addComponent(jTextField5, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE)))) .addGap(27, 27, 27)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel2) .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) 58 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel6) .addComponent(jTextField5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel3)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel1)) .addGap(12, 12, 12) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel5) .addComponent(jPasswordField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) .addComponent(jButton1) .addContainerGap()) ); 59 pack(); }// </editor-fold>//GEN-END:initComponents private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_jButton1ActionPerformed chat.servidorIRC=jTextField1.getText(); chat.endereco=jTextField3.getText(); chat.portaIRC=jTextField5.getText(); chat.porta=jTextField2.getText(); chat.nickname=jTextField4.getText(); chat.btNickname.setText(chat.nickname); chat.password=new String(jPasswordField1.getPassword()); this.setVisible(false); }//GEN-LAST:event_jButton1ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButton1; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JPasswordField jPasswordField1; private javax.swing.JTextField jTextField1; private javax.swing.JTextField jTextField2; 60 private javax.swing.JTextField jTextField3; private javax.swing.JTextField jTextField4; private javax.swing.JTextField jTextField5; // End of variables declaration//GEN-END:variables } 61 Canal.java import java.util.ArrayList; public class Canal { public boolean grupo; public String nome, topico; public ArrayList<String> users; public ArrayList<String> texto; public Canal(String nome,String topico, boolean grupo){ this.nome=nome; this.topico=topico; users=new ArrayList<String>(); texto=new ArrayList<String>(); this.grupo=grupo; } } 62 Chat.java import java.io.DataInputStream; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.ListSelectionModel; public class Chat extends javax.swing.JFrame { private ArrayList<Canal> canais; public String endereco="localhost"; public String porta="6001"; private PrintWriter printer; private DataInputStream reader; private Canal canalSelecionado; private String nomeCanalSelecionado; public String nickname; private JButton fireButton; private DefaultListModel listModel; private String userpvt; 63 public String servidorIRC, servidor,password; private Preferencias preferencias; public String portaIRC; private Socket sock; public String exNickname; /** Creates new form Chat */ public Chat() { try{ servidorIRC="193.137.208.208"; portaIRC="6667"; endereco="localhost"; porta="6001"; password="admin"; preferencias=new Preferencias(this); canais=new ArrayList<Canal>(); canalSelecionado=new Canal("ptnet","",false); canais.add(canalSelecionado); nomeCanalSelecionado="ptnet"; nickname="prudiperv"; exNickname=nickname; }catch(Exception e){ e.printStackTrace(); } initComponents(); jcCanais.addItem(nomeCanalSelecionado); listModel = new DefaultListModel(); 64 jlUtilizadores.setModel(listModel); jlUtilizadores.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); jlUtilizadores.setSelectedIndex(0); } @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GENBEGIN:initComponents private void initComponents() { jScrollPane1 = new javax.swing.JScrollPane(); jtTexto = new javax.swing.JTextArea(); jtMensagem = new javax.swing.JTextField(); jButton1 = new javax.swing.JButton(); jScrollPane2 = new javax.swing.JScrollPane(); jlUtilizadores = new javax.swing.JList(); jcCanais = new javax.swing.JComboBox(); jLabel1 = new javax.swing.JLabel(); jcEstado = new javax.swing.JComboBox(); btNickname = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); jMenuBar1 = new javax.swing.JMenuBar(); jMenu1 = new javax.swing.JMenu(); jMenuItem1 = new javax.swing.JMenuItem(); jMenuItem2 = new javax.swing.JMenuItem(); 65 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Chat"); jtTexto.setColumns(20); jtTexto.setEditable(false); jtTexto.setRows(5); jScrollPane1.setViewportView(jtTexto); jtMensagem.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { jtMensagemKeyPressed(evt); } }); jButton1.setText("OK"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jlUtilizadores.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { jlUtilizadoresMouseClicked(evt); } }); 66 jlUtilizadores.addListSelectionListener(new javax.swing.event.ListSelectionListener() { public void valueChanged(javax.swing.event.ListSelectionEvent evt) { jlUtilizadoresValueChanged(evt); } }); jScrollPane2.setViewportView(jlUtilizadores); jcCanais.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { jcCanaisItemStateChanged(evt); } }); jLabel1.setText("Estado:"); jcEstado.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Disponível", "Ausente" })); jcEstado.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { jcEstadoItemStateChanged(evt); } }); btNickname.setText("prudiperv"); btNickname.setActionCommand("nickname"); jButton2.setFont(new java.awt.Font("Arial", 1, 10)); jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/close.png"))); 67 jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); jMenu1.setText("Chat"); jMenuItem1.setText("Preferências"); jMenuItem1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem1ActionPerformed(evt); } }); jMenu1.add(jMenuItem1); jMenuItem2.setText("Ligar"); jMenuItem2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem2ActionPerformed(evt); } }); jMenu1.add(jMenuItem2); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); 68 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(24, 24, 24) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(25, 25, 25) .addComponent(jcCanais, javax.swing.GroupLayout.PREFERRED_SIZE, 184, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(btNickname, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(18, 18, 18)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, 69 layout.createSequentialGroup() .addComponent(jcEstado, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(23, 23, 23))))) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jtMensagem, javax.swing.GroupLayout.DEFAULT_SIZE, 641, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 703, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addGap(63, 63, 63) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(32, 32, 32)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jcCanais, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE) 70 .addGap(395, 395, 395) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(jcEstado)) .addGap(72, 72, 72)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jtMensagem, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btNickname) .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()))) ); pack(); }// </editor-fold>//GEN-END:initComponents private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_jButton1ActionPerformed enviarMensagem(jtMensagem.getText()); 71 }//GEN-LAST:event_jButton1ActionPerformed private void jtMensagemKeyPressed(java.awt.event.KeyEvent evt) {//GENFIRST:event_jtMensagemKeyPressed if(evt.getKeyCode()==evt.VK_ENTER) enviarMensagem(jtMensagem.getText()); }//GEN-LAST:event_jtMensagemKeyPressed private void jcCanaisItemStateChanged(java.awt.event.ItemEvent evt) {//GENFIRST:event_jcCanaisItemStateChanged nomeCanalSelecionado=(String)jcCanais.getSelectedItem(); canalSelecionado=procuraCanal(nomeCanalSelecionado.trim()); listModel = new DefaultListModel(); if(canalSelecionado!=null){ for(String str: canalSelecionado.users) listModel.addElement(str); jlUtilizadores.setModel(listModel); jtTexto.setText(""); for(String str: canalSelecionado.texto) jtTexto.append(str+"\n"); jtTexto.selectAll(); } }//GEN-LAST:event_jcCanaisItemStateChanged private void jcEstadoItemStateChanged(java.awt.event.ItemEvent evt) {//GENFIRST:event_jcEstadoItemStateChanged if( evt.getStateChange() == evt.SELECTED && jcEstado.getSelectedIndex()==0){ printer.println("away "); printer.flush(); 72 }else if( evt.getStateChange() == evt.SELECTED ){ printer.println("away "); printer.flush(); } }//GEN-LAST:event_jcEstadoItemStateChanged private void jlUtilizadoresMouseClicked(java.awt.event.MouseEvent evt) {//GENFIRST:event_jlUtilizadoresMouseClicked System.out.println(userpvt); openPvt(userpvt); }//GEN-LAST:event_jlUtilizadoresMouseClicked private void jlUtilizadoresValueChanged(javax.swing.event.ListSelectionEvent evt) {//GENFIRST:event_jlUtilizadoresValueChanged if (jlUtilizadores.getSelectedIndex() >-1) { userpvt=(String)jlUtilizadores.getSelectedValue(); } }//GEN-LAST:event_jlUtilizadoresValueChanged private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_jButton2ActionPerformed if(!nomeCanalSelecionado.equals("ptnet")){ if(canalSelecionado.grupo){ printer.println("PART "+nomeCanalSelecionado); printer.flush(); } canais.remove(canalSelecionado); jcCanais.removeItem(nomeCanalSelecionado.trim()); 73 nomeCanalSelecionado=(String)jcCanais.getSelectedItem(); canalSelecionado=procuraCanal(nomeCanalSelecionado); } }//GEN-LAST:event_jButton2ActionPerformed private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_jMenuItem1ActionPerformed preferencias.setVisible(true); }//GEN-LAST:event_jMenuItem1ActionPerformed private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_jMenuItem2ActionPerformed try { InetAddress svc_ip = InetAddress.getByName(endereco); sock = new Socket(svc_ip, new Integer(porta)); printer = new PrintWriter(sock.getOutputStream(), true); //IP <ip> [<porta>] //INIT <nick> [<password>] printer.println("IP "+servidorIRC+" "+portaIRC); printer.println("INIT "+nickname+" "+password); printer.flush(); reader = new DataInputStream(sock.getInputStream()); Leitura leitura=new Leitura(); leitura.start(); } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.getMessage()); } }//GEN-LAST:event_jMenuItem2ActionPerformed 74 private void openPvt(String user){ if(user.startsWith("@") || user.startsWith("+")) user=user.substring(1,user.length()).trim(); Canal c=procuraCanal(user); nomeCanalSelecionado=user; if(c!=null){ canalSelecionado=c; }else{ canalSelecionado=new Canal(nomeCanalSelecionado,"",false); canais.add(canalSelecionado); jcCanais.addItem(nomeCanalSelecionado); } jcCanais.setSelectedItem(nomeCanalSelecionado); } private Canal procuraCanal(String str){ for(Canal c: canais){ if(c.nome.equals(str)) return c; } return null; } private void enviarMensagem(String text) { if(!text.isEmpty()){ 75 jtMensagem.setText(""); try{ if(text.startsWith("/")){ if(text.length()>7 && text.substring(0,7).equals("/join #")){ String vec[]=text.split(" "); nomeCanalSelecionado=vec[1]; Canal c=procuraCanal(nomeCanalSelecionado); if(c!=null){ canalSelecionado=c; }else{ canalSelecionado=new Canal(vec[1],"",true); canais.add(canalSelecionado); jcCanais.addItem(nomeCanalSelecionado); } jcCanais.setSelectedItem(nomeCanalSelecionado); printer.println(text.substring(1,text.length())); printer.flush(); }else if(text.startsWith("/nick ")){ // String vec[]=text.split(" "); // nickname=vec[1].trim(); // btNickname.setText(nickname); printer.println(text.substring(1,text.length())); printer.flush(); }else if(text.startsWith("/query")){ String vec[]=text.split(" "); nomeCanalSelecionado=vec[1].trim(); Canal c=procuraCanal(nomeCanalSelecionado); 76 if(c!=null){ canalSelecionado=c; }else{ canalSelecionado=new Canal(nomeCanalSelecionado,"",false); canais.add(canalSelecionado); jcCanais.addItem(nomeCanalSelecionado); } jcCanais.setSelectedItem(nomeCanalSelecionado); text=""; if(vec.length>2){ for(int i = 2; i< vec.length; i++){ text+=" "+vec[i]; } } if(!text.isEmpty()){ canalSelecionado.texto.add(nickname+" diz: "+text+"\n"); jtTexto.append(nickname+" diz: "+text+"\n"); printer.println("PRIVMSG "+nomeCanalSelecionado+" :"+text); printer.flush(); } }else if(text.startsWith("/exit")){ sock.close(); printer.println("EXIT"); printer.flush(); 77 }else if(text.startsWith("/msg ")){ String [] vec= text.split(" "); String nick=vec[1].trim(); String sms=""; for(int i=2;i<vec.length;i++) sms+=vec[i]+" "; printer.println("PRIVMSG "+nick+" : "+sms); printer.flush(); }else if(text.startsWith("/away")){ if(jcEstado.getSelectedIndex()==0) jcEstado.setSelectedIndex(1); else jcEstado.setSelectedIndex(0); String [] vec = text.split(" "); String txt=""; for(int i =1;i<vec.length;i++) txt+=vec[i]+" "; printer.println("away "+txt); printer.flush(); }else{ printer.println(text.substring(1,text.length())); printer.flush(); } 78 }else{ printer.println("PRIVMSG "+nomeCanalSelecionado+" :"+text); printer.flush(); canalSelecionado.texto.add(nickname+" diz: "+text); jtTexto.append(nickname+" diz: "+text+"\n"); } jtTexto.selectAll(); }catch(Exception e){ e.printStackTrace(); } } } class Leitura extends Thread { Leitura() {} public void run() { while(true){ try { byte[] buf = new byte[2048]; reader.read(buf); String txt = new String(buf, 0, buf.length); if(txt.length()>11 && txt.startsWith("GMSG")){ //receber mensagem de grupo String [] vec = txt.split("-"); Canal c= procuraCanal(vec[2].trim()); 79 if(c!=null){ txt=vec[3]; if(vec.length>4) for(int i=4;i<vec.length;i++) txt+="-"+vec[i]; c.texto.add(vec[1]+" diz: "+txt); if(c.nome.equals(nomeCanalSelecionado)) jtTexto.append(vec[1]+" diz: "+txt+"\n"); } }else if (txt.length()>8 && txt.startsWith("PMSG")){ //receber mensagem privada String [] vec =txt.split("-"); Canal c=procuraCanal(vec[1].trim()); if(c== null){ c=new Canal(vec[1].trim(),"",false); canais.add(c); jcCanais.addItem(c.nome); } txt=vec[2]; if(vec.length>3) for(int i=3;i<vec.length;i++) txt+="-"+vec[i]; c.texto.add(vec[1]+" diz: "+txt); if(c.nome.equals(nomeCanalSelecionado)) jtTexto.append(vec[1]+" diz: "+txt+"\n"); 80 }else if(txt.length()>8 && txt.startsWith("JOIN")){//JOIN-imonxixilau-#b320 String [] vec = txt.split("-"); vec[2]=vec[2].trim(); Canal c=procuraCanal(vec[2]); if(c!=null){ if(nomeCanalSelecionado.equals(vec[2])){ jtTexto.append("O utilizador "+vec[1]+" entrou no canal\n"); if(!listModel.contains(vec[1])) listModel.addElement(vec[1]); } c.texto.add("O utilizador "+vec[1]+" entrou no canal\n"); c.users.add(vec[1]); } }else if(txt.length()>8 && txt.startsWith("PART")){//PART-johnprudence-#b320 String [] vec = txt.split("-"); vec[2]=vec[2].trim(); Canal c=procuraCanal(vec[2]); if(c!=null){ if(nomeCanalSelecionado.equals(vec[2])){ jtTexto.append("O utilizador "+vec[1]+" saiu do canal\n"); if(listModel.contains(vec[1])) listModel.removeElement(vec[1]); } c.texto.add("O utilizador "+vec[1]+" saiu do canal\n"); c.users.remove(vec[1]); } }else if(txt.contains("QUIT :")){ 81 String [] vec = txt.split("!"); String uzer = vec[0].substring(1,vec[0].length()); uzer = uzer.trim(); if(listModel.contains(uzer)){ listModel.removeElement(uzer); jtTexto.append(txt + "\n"); Canal c=procuraCanal(nomeCanalSelecionado); c.texto.add(txt + "\n"); } for(Canal c: canais){ if(c.users.contains(uzer)){ c.users.remove(uzer); } } }else if(txt.startsWith("GROUP")){ String [] vec = txt.split(" "); if(vec[1].trim().equals("(null)")){ System.out.println("nulada"); }else{ listModel.removeAllElements(); for(int i=1;i<vec.length;i++){ String nome; /* if(vec[i].startsWith("@")) nome=vec[i].substring(1,vec[i].length()).trim(); else*/ 82 nome=vec[i].trim(); listModel.addElement(nome); if(!canalSelecionado.users.contains(nome)) canalSelecionado.users.add(nome); } } }else if(txt.contains("KICK")){ String [] vec = txt.split("#"); String [] vec2 = vec[1].split(" "); String kickado = vec2[1].trim(); String kickC = "#"+vec2[0].trim(); if(kickC.equals(nomeCanalSelecionado)){ listModel.removeElement(kickado); jtTexto.append(txt + "\n"); jcCanais.removeItem(nomeCanalSelecionado); nomeCanalSelecionado=(String)jcCanais.getSelectedItem(); canalSelecionado=procuraCanal(nomeCanalSelecionado); } Canal c= procuraCanal(kickC); c.users.remove(kickado); canalSelecionado.texto.add(txt); }else if(txt.contains("NICK :")){ String [] vec = txt.split(":"); String [] vec2=vec[vec.length-2].split("!"); 83 exNickname=vec2[0].trim(); nickname=vec[vec.length-1].trim(); System.out.println(exNickname+" para " +nickname); btNickname.setText(nickname); for(Canal c: canais){ if(c.users.contains(exNickname) ){ c.users.remove(exNickname); c.users.add(nickname); }else if(c.users.contains("+"+exNickname) ){ c.users.remove("+"+exNickname); c.users.add("+"+exNickname); }else if(c.users.contains("@"+exNickname) ){ c.users.remove("@"+exNickname); c.users.add("@"+exNickname); } } if(listModel.contains(exNickname)){ listModel.removeElement(exNickname); listModel.addElement(nickname); }else if(listModel.contains("@"+exNickname)){ listModel.removeElement("@"+exNickname); listModel.addElement("@"+nickname); }else if(listModel.contains("+"+exNickname)){ listModel.removeElement("+"+exNickname); 84 listModel.addElement("+"+nickname); } jtTexto.append(txt + "\n"); canalSelecionado.texto.add(txt); }else if(txt.contains("ERRO <nick>")){ btNickname.setText(exNickname); for(Canal c: canais) for(String u: c.users) if(u.equals(nickname)) u=exNickname; if(listModel.contains(nickname)){ int x=listModel.indexOf(nickname); listModel.set(x,exNickname); } nickname=exNickname; jtTexto.append(txt + "\n"); canalSelecionado.texto.add(txt); }else { jtTexto.append(txt + "\n"); 85 canalSelecionado.texto.add(txt); } jtTexto.selectAll(); } catch (IOException ex) { ex.printStackTrace(); } } } } public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Chat().setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables public javax.swing.JButton btNickname; private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JLabel jLabel1; private javax.swing.JMenu jMenu1; private javax.swing.JMenuBar jMenuBar1; private javax.swing.JMenuItem jMenuItem1; 86 private javax.swing.JMenuItem jMenuItem2; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JComboBox jcCanais; private javax.swing.JComboBox jcEstado; private javax.swing.JList jlUtilizadores; private javax.swing.JTextField jtMensagem; private javax.swing.JTextArea jtTexto; // End of variables declaration//GEN-END:variables } 87 Preferencias.form <?xml version="1.0" encoding="UTF-8" ?> <Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> <Properties> <Property name="title" type="java.lang.String" value="Preferências"/> </Properties> <SyntheticProperties> <SyntheticProperty name="formSizePolicy" type="int" value="1"/> </SyntheticProperties> <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> </AuxValues> <Layout> <DimensionLayout dim="0"> 88 <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Component id="jButton1" min="-2" max="-2" attributes="0"/> </Group> <Group type="102" alignment="1" attributes="0"> <EmptySpace min="-2" pref="28" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jLabel3" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace min="-2" pref="33" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jTextField4" pref="182" max="32767" attributes="0"/> <Component id="jTextField2" alignment="1" pref="182" max="32767" attributes="1"/> <Component id="jTextField3" alignment="0" pref="182" max="32767" attributes="0"/> <Component id="jTextField1" pref="182" max="32767" attributes="1"/> <Component id="jPasswordField1" alignment="1" pref="182" max="32767" attributes="0"/> <Component id="jTextField5" alignment="0" pref="182" max="32767" attributes="0"/> 89 </Group> </Group> </Group> <EmptySpace min="27" pref="27" max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> <DimensionLayout dim="1"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel2" min="-2" max="-2" attributes="0"/> <Component id="jTextField1" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jTextField5" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jTextField3" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> 90 <Component id="jTextField2" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jTextField4" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace min="-2" pref="12" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel5" min="-2" max="-2" attributes="0"/> <Component id="jPasswordField1" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace pref="18" max="32767" attributes="0"/> <Component id="jButton1" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> </Layout> <SubComponents> <Component class="javax.swing.JLabel" name="jLabel1"> <Properties> <Property name="text" type="java.lang.String" value="Nickname:"/> </Properties> </Component> <Component class="javax.swing.JLabel" name="jLabel2"> 91 <Properties> <Property name="text" type="java.lang.String" value="Servidor IRC:"/> </Properties> </Component> <Component class="javax.swing.JLabel" name="jLabel3"> <Properties> <Property name="text" type="java.lang.String" value="Porta:"/> </Properties> </Component> <Component class="javax.swing.JTextField" name="jTextField1"> <Properties> <Property name="text" type="java.lang.String" value="193.137.208.208"/> </Properties> </Component> <Component class="javax.swing.JTextField" name="jTextField2"> <Properties> <Property name="text" type="java.lang.String" value="6001"/> </Properties> </Component> <Component class="javax.swing.JTextField" name="jTextField3"> <Properties> <Property name="text" type="java.lang.String" value="localhost"/> </Properties> </Component> <Component class="javax.swing.JLabel" name="jLabel4"> <Properties> <Property name="text" type="java.lang.String" value="Servidor: "/> 92 </Properties> </Component> <Component class="javax.swing.JTextField" name="jTextField4"> <Properties> <Property name="text" type="java.lang.String" value="prudiperv"/> </Properties> </Component> <Component class="javax.swing.JLabel" name="jLabel5"> <Properties> <Property name="text" type="java.lang.String" value="Password:"/> </Properties> </Component> <Component class="javax.swing.JPasswordField" name="jPasswordField1"> <Properties> <Property name="text" type="java.lang.String" value="admin"/> </Properties> </Component> <Component class="javax.swing.JButton" name="jButton1"> <Properties> <Property name="text" type="java.lang.String" value="Confirmar"/> </Properties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> </Events> </Component> <Component class="javax.swing.JLabel" name="jLabel6"> <Properties> 93 <Property name="text" type="java.lang.String" value="Porta IRC:"/> </Properties> </Component> <Component class="javax.swing.JTextField" name="jTextField5"> <Properties> <Property name="text" type="java.lang.String" value="6667"/> </Properties> </Component> </SubComponents> </Form> 94 Chat.form <?xml version="1.0" encoding="UTF-8" ?> <Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> <NonVisualComponents> <Menu class="javax.swing.JMenuBar" name="jMenuBar1"> <SubComponents> <Menu class="javax.swing.JMenu" name="jMenu1"> <Properties> <Property name="text" type="java.lang.String" value="Chat"/> </Properties> <SubComponents> <MenuItem class="javax.swing.JMenuItem" name="jMenuItem1"> <Properties> <Property name="text" type="java.lang.String" value="Preferências"/> </Properties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuItem1ActionPerformed"/> </Events> </MenuItem> <MenuItem class="javax.swing.JMenuItem" name="jMenuItem2"> <Properties> <Property name="text" type="java.lang.String" value="Ligar"/> </Properties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" 95 parameters="java.awt.event.ActionEvent" handler="jMenuItem2ActionPerformed"/> </Events> </MenuItem> </SubComponents> </Menu> </SubComponents> </Menu> </NonVisualComponents> <Properties> <Property name="defaultCloseOperation" type="int" value="3"/> <Property name="title" type="java.lang.String" value="Chat"/> </Properties> <SyntheticProperties> <SyntheticProperty name="menuBar" type="java.lang.String" value="jMenuBar1"/> <SyntheticProperty name="formSizePolicy" type="int" value="1"/> </SyntheticProperties> <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> 96 </AuxValues> <Layout> <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> <EmptySpace min="-2" pref="24" max="-2" attributes="0"/> <Group type="103" groupAlignment="1" attributes="0"> <Component id="jButton2" alignment="1" min="-2" pref="37" max="-2" attributes="0"/> <Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> <EmptySpace min="-2" pref="25" max="-2" attributes="0"/> <Component id="jcCanais" min="-2" pref="184" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> </Group> <Group type="102" alignment="1" attributes="0"> <Component id="jLabel1" min="-2" pref="63" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="102" alignment="1" attributes="1"> <Component id="btNickname" max="32767" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/> </Group> <Group type="102" alignment="1" attributes="0"> <Component id="jcEstado" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="23" max="-2" attributes="0"/> 97 </Group> </Group> </Group> </Group> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" attributes="0"> <Component id="jtMensagem" pref="641" max="32767" attributes="1"/> <EmptySpace max="-2" attributes="0"/> <Component id="jButton1" min="-2" pref="56" max="-2" attributes="1"/> </Group> <Component id="jScrollPane1" min="-2" pref="703" max="-2" attributes="1"/> </Group> </Group> </Group> <EmptySpace min="-2" pref="63" max="-2" attributes="0"/> <Component id="jScrollPane2" min="-2" pref="124" max="-2" attributes="1"/> <EmptySpace min="-2" pref="32" max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> <DimensionLayout dim="1"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Component id="jButton2" min="-2" pref="29" max="-2" attributes="1"/> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> 98 <Group type="102" alignment="1" attributes="0"> <Component id="jcCanais" min="-2" pref="34" max="-2" attributes="0"/> <EmptySpace min="-2" pref="395" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="1"/> <Component id="jcEstado" alignment="3" max="32767" attributes="1"/> </Group> <EmptySpace min="-2" pref="72" max="-2" attributes="0"/> </Group> <Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0"> <Component id="jScrollPane2" alignment="1" pref="473" max="32767" attributes="1"/> <Component id="jScrollPane1" alignment="1" pref="473" max="32767" attributes="1"/> </Group> <EmptySpace type="unrelated" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jtMensagem" alignment="3" min="-2" pref="31" max="-2" attributes="0"/> <Component id="btNickname" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jButton1" alignment="3" min="-2" pref="32" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> </Group> </Group> </Group> 99 </Group> </DimensionLayout> </Layout> <SubComponents> <Container class="javax.swing.JScrollPane" name="jScrollPane1"> <AuxValues> <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> </AuxValues> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> <SubComponents> <Component class="javax.swing.JTextArea" name="jtTexto"> <Properties> <Property name="columns" type="int" value="20"/> <Property name="editable" type="boolean" value="false"/> <Property name="rows" type="int" value="5"/> </Properties> </Component> </SubComponents> </Container> <Component class="javax.swing.JTextField" name="jtMensagem"> <Events> <EventHandler event="keyPressed" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="jtMensagemKeyPressed"/> </Events> </Component> <Component class="javax.swing.JButton" name="jButton1"> 100 <Properties> <Property name="text" type="java.lang.String" value="OK"/> </Properties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> </Events> </Component> <Container class="javax.swing.JScrollPane" name="jScrollPane2"> <AuxValues> <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> </AuxValues> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> <SubComponents> <Component class="javax.swing.JList" name="jlUtilizadores"> <Properties> <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor"> <StringArray count="0"/> </Property> </Properties> <Events> <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jlUtilizadoresMouseClicked"/> <EventHandler event="valueChanged" listener="javax.swing.event.ListSelectionListener" parameters="javax.swing.event.ListSelectionEvent" handler="jlUtilizadoresValueChanged"/> </Events> 101 </Component> </SubComponents> </Container> <Component class="javax.swing.JComboBox" name="jcCanais"> <Properties> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> <StringArray count="0"/> </Property> </Properties> <Events> <EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="jcCanaisItemStateChanged"/> </Events> </Component> <Component class="javax.swing.JLabel" name="jLabel1"> <Properties> <Property name="text" type="java.lang.String" value="Estado:"/> </Properties> </Component> <Component class="javax.swing.JComboBox" name="jcEstado"> <Properties> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> <StringArray count="2"> <StringItem index="0" value="Disponível"/> <StringItem index="1" value="Ausente"/> </StringArray> </Property> 102 </Properties> <Events> <EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="jcEstadoItemStateChanged"/> </Events> </Component> <Component class="javax.swing.JButton" name="btNickname"> <Properties> <Property name="text" type="java.lang.String" value="prudiperv"/> <Property name="actionCommand" type="java.lang.String" value="nickname"/> </Properties> <AuxValues> <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="1"/> </AuxValues> </Component> <Component class="javax.swing.JButton" name="jButton2"> <Properties> <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> <Font name="Arial" size="10" style="1"/> </Property> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Image iconType="3" name="/close.png"/> </Property> </Properties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" 103 parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/> </Events> </Component> </SubComponents> </Form> 104