Hoje li uma matéria no Folha Online - Informática que dizia sobre um aluno de 15 anos que foi processado após ter descoberto uma falha no sistema da escola e avisado ao diretor.
No último parágrafo da notícia, a Folha Online usa o termpo "piratas virtuais", enquanto que na notícia do site The Register, de onde eles provavelmente tiraram as informações, de acordo com o que diz o segundo parágrafo do texto da Folha Online, usou-se o termo "hacker" (para informar que os hackers criticaram a decisão de processar o jovem, já que ele não usou a falha pra prejudicar a escola e, ao invés disso, informou o problema ao diretor, que deveria apenas corrigir e agradecer o aviso).
Então, mandei a mensagem abaixo pro pessoal da Folha Online:
"Acho que não deveriam usar o termo 'piratas virtuais' no último parágrafo. Lendo a notícia original no The Register, eles dizem '...hackers have criticized...'. A mídia precisa entender que hacker não é vândalo nem pirata, esses últimos são chamados 'crackers'. Hackers são pessoas que estudam a fundo aquilo que gostam ou praticam ao ponto de fazer coisas que muitos possam achar politicamente incorreto. Por exemplo: um hacker pode criar um vírus com o intuito de aprender novas técnicas de programação, mas apenas o cracker disseminaria esse vírus com o intuito de prejudicar terceiros. Outro exemplo que achei bom, foi quando Richard Stallman disse que 'Gilberto Gil é um hacker da música'. Espero ter contribuído."
Fiz minha parte. Porém, minutos depois, recebi o seguinte e-mail da Folha Online:
"Prezado leitor, a Folha Online não utiliza o termo 'hackers'.
Esperamos contar sempre com sua leitura e participação
Atenciosamente,
Equipe Folha Online"
Fiquei decepcionado. Por que? Porque um jornal, formador de opinião, deveria usar os termos corretos. Dessa forma, os leitores acreditam que qualquer pessoa que descobre falhas em sistemas é um pirata virtual ou criminoso da informática. A mídia deveria usar os termos corretos, para que os hackers de verdade não fossem mais taxados de foras da lei.
Inclusive, pesquisando o termo "hacker" no próprio site do jornal, pude ver que eles usam sim a palavra "hacker". Vejam o resultado da pesquisa!
quarta-feira, outubro 29, 2008
quarta-feira, setembro 03, 2008
Google Chrome
Instalei hoje nos PCs da RG3. Não pude instalar no meu notebook pois ainda não fizeram o Chrome pra Linux :(
A primeira impressão que tive é que ele realmente é bem simples. Navegador foi feito pra navegar e pronto. Nada de frescuragem. Se o Firefox simplificou a cara dos navegadores, o Chrome simplificou mais ainda (e o Internet Explorer acabou tendo que acompanhar o Firefox nesse quesito).
A segunda impressão que tive é que o bixo é realmente rápido! Nunca vi coisa igual. Não sei se é porque o cache dele ainda está vazio, mas a velocidade me impressionou. Ele usa o mesmo engine do Safari, o WebKit. Inclusive, olhando o User-Agent do Chrome, vi que tem um Safari no final da string (não pude colar a string inteira aqui porque estou escrevendo esse post pelo Linux, vou pegar a string no Windows e colocar aqui depois).
Li também toda a estória em quadrinhos que a Google fez pro lançamento do Chrome e pude concluir que eles fizeram um navegador da complexidade de um sistema operacional, muito violento. Inclusive a forma de tratar as coisas, com vários processos, isolamento entre eles, etc., ficou muito bom e bem pensado.
A terceira coisa que gostei nele foi a página "New tab", que aparece quando você abre uma nova aba. Nessa página, são mostrados os thumbnails dos nove sites mais acessados, além das pesquisas mais recentes. Basta um clique pra reabrir uma página.
O site oficial está em www.google.com/chrome.
Pra quem não sabe do que estou falando ainda, leiam essa notícia.
A primeira impressão que tive é que ele realmente é bem simples. Navegador foi feito pra navegar e pronto. Nada de frescuragem. Se o Firefox simplificou a cara dos navegadores, o Chrome simplificou mais ainda (e o Internet Explorer acabou tendo que acompanhar o Firefox nesse quesito).
A segunda impressão que tive é que o bixo é realmente rápido! Nunca vi coisa igual. Não sei se é porque o cache dele ainda está vazio, mas a velocidade me impressionou. Ele usa o mesmo engine do Safari, o WebKit. Inclusive, olhando o User-Agent do Chrome, vi que tem um Safari no final da string (não pude colar a string inteira aqui porque estou escrevendo esse post pelo Linux, vou pegar a string no Windows e colocar aqui depois).
Li também toda a estória em quadrinhos que a Google fez pro lançamento do Chrome e pude concluir que eles fizeram um navegador da complexidade de um sistema operacional, muito violento. Inclusive a forma de tratar as coisas, com vários processos, isolamento entre eles, etc., ficou muito bom e bem pensado.
A terceira coisa que gostei nele foi a página "New tab", que aparece quando você abre uma nova aba. Nessa página, são mostrados os thumbnails dos nove sites mais acessados, além das pesquisas mais recentes. Basta um clique pra reabrir uma página.
O site oficial está em www.google.com/chrome.
Pra quem não sabe do que estou falando ainda, leiam essa notícia.
quinta-feira, agosto 28, 2008
Do FreeBSD 4.7 ao 7.0
Em 7 de fevereiro deste ano, escrevi um post contando minha trajetória pelo Linux. Nos comentários deste post, um Anônimo pediu pra eu contar minha trajetória pelo FreeBSD.
Pois bem, a vida com FreeBSD também começou quando eu cursava Física na UEFS. Eu já estava me familiarizando com os RedHats 7.0 do Laboratório de Física Computacional e, inclusive, já havia instalado ele em um servidor de impressão que tinha no laboratório. Não era uma máquina parruda, apenas um Pentium 233 MHz com 64 MB de RAM.
Dois colegas de curso, Alex Gamas e Leonardo Gamas (irmãos) eram uma das minhas principais fontes de conhecimento em Linux, seguidos por Jorge Kaschy, Nazareno e Dagoberto Freitas (estes três últimos, professores), e foram os irmãos Gamas que me apresentaram o FreeBSD.
Na época, consegui um CD de instalação do FreeBSD 4.7, não lembro se foram eles que me conseguiram ou se eu baixei na Internet. Tirei o RedHat 7.0 do servidorzinho e instalei o Free. Com o Samba, eu fiz um controlador de domínio e os alunos do curso passaram a ter login e senha para acessar as máquinas. Isso ajudou bastante, porque na Universidade, vinha gente de todo canto, às vezes nem aluno era, e ficavam enchendo as máquinas com vírus.
Com o Samba e o FreeBSD 4.7 fiz também um servidor de impressão. O pessoal gostou muito. Tinham 20 MB de espaço no HD pra salvar trabalhos e podiam imprimir sem os problemas que davam antes no Windows NT, que era o sistema do servidor antes do RedHat.
O esquema de PDC (controlador de domínio) fez tanto sucesso na Universidade que um professor do curso de Matemática me chamou pra ajudar ele a fazer o mesmo no laboratório de lá. Inclusive, alguns alunos de outros cursos vinham me pedir pra usarem os PCs do nosso laboratório, pois tínhamos a fama de "o único laboratório da UEFS sem vírus", mas isso não tem nada a ver com o FreeBSD no servidor, tem a ver com as políticas de segurança que eu aplicava nos Windows NT dos PCs. Em 2004 fui pra Ilhéus cursar Ciência da Computação na UESC e desde então, nunca mais havia usado um FreeBSD.
Em 2006, quando comecei a ajudar os funcionários da RG3.Net a dar manuntenção nos servidores foi que me reencontrei com o FreeBSD, desta vez, na versão 5.2.
Em 2007, assumi a propriedade da RG3.Net e desde então, fiz algumas atualizações. O servidor do provedor tornou-se FreeBSD 6.2 (instalei uma máquina nova com o sistema do zero), que posteriormente foi atualizado para 6.3. Hoje em dia, temos outro servidor novo, com o FreeBSD 7.0. O servidor do site também foi atualizado pra versão 7.
Nessa retomada no mundo do FreeBSD foi que eu aprendi várias coisas, como usar o ports e outros programas correlatos como portsnap, portupgrade e freebsd-update.
Hoje em dia uso FreeBSD diariamente, não no meu desktop, mas nos servidores e estou feliz com isso. Inclusive, após usar Linux em servidores por muito tempo lá em Ilhéus e voltando pro FreeBSD aqui em Feira de Santana, posso afirmar: em se tratando de servidores de rede, considero o FreeBSD muito mais fácil de configurar e usar.
Pois bem, a vida com FreeBSD também começou quando eu cursava Física na UEFS. Eu já estava me familiarizando com os RedHats 7.0 do Laboratório de Física Computacional e, inclusive, já havia instalado ele em um servidor de impressão que tinha no laboratório. Não era uma máquina parruda, apenas um Pentium 233 MHz com 64 MB de RAM.
Dois colegas de curso, Alex Gamas e Leonardo Gamas (irmãos) eram uma das minhas principais fontes de conhecimento em Linux, seguidos por Jorge Kaschy, Nazareno e Dagoberto Freitas (estes três últimos, professores), e foram os irmãos Gamas que me apresentaram o FreeBSD.
Na época, consegui um CD de instalação do FreeBSD 4.7, não lembro se foram eles que me conseguiram ou se eu baixei na Internet. Tirei o RedHat 7.0 do servidorzinho e instalei o Free. Com o Samba, eu fiz um controlador de domínio e os alunos do curso passaram a ter login e senha para acessar as máquinas. Isso ajudou bastante, porque na Universidade, vinha gente de todo canto, às vezes nem aluno era, e ficavam enchendo as máquinas com vírus.
Com o Samba e o FreeBSD 4.7 fiz também um servidor de impressão. O pessoal gostou muito. Tinham 20 MB de espaço no HD pra salvar trabalhos e podiam imprimir sem os problemas que davam antes no Windows NT, que era o sistema do servidor antes do RedHat.
O esquema de PDC (controlador de domínio) fez tanto sucesso na Universidade que um professor do curso de Matemática me chamou pra ajudar ele a fazer o mesmo no laboratório de lá. Inclusive, alguns alunos de outros cursos vinham me pedir pra usarem os PCs do nosso laboratório, pois tínhamos a fama de "o único laboratório da UEFS sem vírus", mas isso não tem nada a ver com o FreeBSD no servidor, tem a ver com as políticas de segurança que eu aplicava nos Windows NT dos PCs. Em 2004 fui pra Ilhéus cursar Ciência da Computação na UESC e desde então, nunca mais havia usado um FreeBSD.
Em 2006, quando comecei a ajudar os funcionários da RG3.Net a dar manuntenção nos servidores foi que me reencontrei com o FreeBSD, desta vez, na versão 5.2.
Em 2007, assumi a propriedade da RG3.Net e desde então, fiz algumas atualizações. O servidor do provedor tornou-se FreeBSD 6.2 (instalei uma máquina nova com o sistema do zero), que posteriormente foi atualizado para 6.3. Hoje em dia, temos outro servidor novo, com o FreeBSD 7.0. O servidor do site também foi atualizado pra versão 7.
Nessa retomada no mundo do FreeBSD foi que eu aprendi várias coisas, como usar o ports e outros programas correlatos como portsnap, portupgrade e freebsd-update.
Hoje em dia uso FreeBSD diariamente, não no meu desktop, mas nos servidores e estou feliz com isso. Inclusive, após usar Linux em servidores por muito tempo lá em Ilhéus e voltando pro FreeBSD aqui em Feira de Santana, posso afirmar: em se tratando de servidores de rede, considero o FreeBSD muito mais fácil de configurar e usar.
sábado, agosto 23, 2008
Enquanto isso...
...já anunciaram as datas previstas para o lançamento do FreeBSD 6.4 e do 7.1.
Estou ansioso pra atualizar pro 7.1. O 7.0 está rodando bem aqui, mas tive alguns problemas com o ppp. Mas isso é assunto pra outro post.
Estou ansioso pra atualizar pro 7.1. O 7.0 está rodando bem aqui, mas tive alguns problemas com o ppp. Mas isso é assunto pra outro post.
sexta-feira, agosto 22, 2008
Servidores do Fedora invadidos
Olá, pessoal.
Voltei a postar no meu (quase abandonado) blog e a notícia não é boa (não que eu use Fedora, mas invasões nunca são boas).
Fiquei sabendo hoje que alguns servidores do repositório do Fedora foram invadidos. Existe um e-mail na lista de discussão fedora-announce-list que explica melhor o fato:
Infrastructure report
Voltei a postar no meu (quase abandonado) blog e a notícia não é boa (não que eu use Fedora, mas invasões nunca são boas).
Fiquei sabendo hoje que alguns servidores do repositório do Fedora foram invadidos. Existe um e-mail na lista de discussão fedora-announce-list que explica melhor o fato:
Infrastructure report
sexta-feira, março 28, 2008
Distro de tolo
Recebi por e-mail, na lista da FUG-BR. Fiz uma pequena alteração: adicionei o animal na nona estrofe, sendo fiél à versão original de Raulzito.
Letra de Leonardo Menezes Vaz
Música de Raul Seixas
Bah!
Eu devia estar contente, porque eu tenho um emprego
Sou um dito SysAdmin respeitável e ganho mil reais por mês...
Bah!
Eu devia agradecer por ter tido sucesso na vida como SysAdmin
Eu devia estar feliz porque consegui integrar o OpenSuSE com o Windows 2003...
Bah!
Eu devia estar alegre e satisfeito por morar em Porto Alegre
Depois de ter passado fome por vinte dias na Alemanha...
Bah!
Eu devia estar sorrindo e orgulhoso
Por finalmente ter conseguido entrar no Planet SuSE,
Mesmo que todo mundo me zoe e faça disso uma piada jocosa...
Bah!
Eu devia estar contente por ter conseguido tudo isso
mas confesso abestalhado que eu estou decepcionado...
Porque foi tão fácil conseguir, e agora eu me pergunto "e daí?"
Eu tenho uma porção de coisas prá blogar
E eu não posso ficar aqui parado...
Bah!
Eu devia estar feliz pelo Senhor
Ter me concedido o Sábado prá ir com a pessoal
No evento do Tchelinux dar palestra de OpenSUSE...
Bah!
Mesmo falando das facilidades,
da Novell, Microsoft, Lagarto, SLES, YAST
E mesmo assim não ter ninguem que use...
É você olhar no espelho e ver um SysAdmin Júnior
Saber que o YAST é uma ferramenta limitada
E que deixa só dez por cento de sua CPU livre, animal!
E você ainda acredita que ser é um CCNA, MCSS ou MCSE
É grande coisa, e que te garante um lugar no mercado...
Bah,
Eu que não me sento numa cadeira de CPD
Com a boca escancarada cheia de dentes
Esperando o OpenSuSE bootar...
Porque longe dos datacenters onde rodam SLES com YAST
existem servidores BSDs e SysAdmin de verdade que usam vi...
Letra de Leonardo Menezes Vaz
Música de Raul Seixas
Bah!
Eu devia estar contente, porque eu tenho um emprego
Sou um dito SysAdmin respeitável e ganho mil reais por mês...
Bah!
Eu devia agradecer por ter tido sucesso na vida como SysAdmin
Eu devia estar feliz porque consegui integrar o OpenSuSE com o Windows 2003...
Bah!
Eu devia estar alegre e satisfeito por morar em Porto Alegre
Depois de ter passado fome por vinte dias na Alemanha...
Bah!
Eu devia estar sorrindo e orgulhoso
Por finalmente ter conseguido entrar no Planet SuSE,
Mesmo que todo mundo me zoe e faça disso uma piada jocosa...
Bah!
Eu devia estar contente por ter conseguido tudo isso
mas confesso abestalhado que eu estou decepcionado...
Porque foi tão fácil conseguir, e agora eu me pergunto "e daí?"
Eu tenho uma porção de coisas prá blogar
E eu não posso ficar aqui parado...
Bah!
Eu devia estar feliz pelo Senhor
Ter me concedido o Sábado prá ir com a pessoal
No evento do Tchelinux dar palestra de OpenSUSE...
Bah!
Mesmo falando das facilidades,
da Novell, Microsoft, Lagarto, SLES, YAST
E mesmo assim não ter ninguem que use...
É você olhar no espelho e ver um SysAdmin Júnior
Saber que o YAST é uma ferramenta limitada
E que deixa só dez por cento de sua CPU livre, animal!
E você ainda acredita que ser é um CCNA, MCSS ou MCSE
É grande coisa, e que te garante um lugar no mercado...
Bah,
Eu que não me sento numa cadeira de CPD
Com a boca escancarada cheia de dentes
Esperando o OpenSuSE bootar...
Porque longe dos datacenters onde rodam SLES com YAST
existem servidores BSDs e SysAdmin de verdade que usam vi...
segunda-feira, março 10, 2008
O castigo dos 64 bits
Pois eh, quem tem processador de 64 bits sofre pra usar todos os bits.
Meu notebook eh um Athlon X2 64-bits, estava rodando Debian (amd64) nele. Havia problemas com o Flash e outras coisas que so tinham pra 32-bits. Um xunxu (workaround) com bibliotecas de 32-bits resolvia o problema, mas era muito chato fazer isso.
Esse fim de semana instalei o FreeBSD 7.0 (amd64 tambem) nele, ja estava querendo tirar o Linux pra botar FreeBSD fazia um tempo. Instalou direitinho (quer dizer, deu um pouco de trabalho pra dar boot no CD).
O problema eh que o driver da nVidia pra FreeBSD suporta somente i386, ou seja, sem driver oficial pra 64-bits no FreeBSD. Ja meio triste, tentei o driver do X.org, aquele "nv" que a gente usa no xorg.conf. Nada de iniciar o X... problema viu! O jeito foi usar o X com o "vesa", que, obviamente, nao tem os recursos de aceleracao 3D.
E isso nao acontece so no mundo do UNIX nao, tambem usei Windows Vista por umas semanas nesse notebook. Instalei a versao de 64-bits e nem os proprios drivers de 64-bits que vieram no CD do computador funcionaram direito. Como resolvi? Instalei o Windows XP de 32-bits mesmo :(
Acho que vou ter que fazer o mesmo no FreeBSD ou mesmo no Linux (se tiver que voltar pra ele). Pesquisando no Google, encontrei muitas pessoas tendo problemas com SO de 64-bits: drivers faltando, menos pacotes nos repositorios, programas nao-suportados, etc.
Vamos ver no que isso vai dar.
Meu notebook eh um Athlon X2 64-bits, estava rodando Debian (amd64) nele. Havia problemas com o Flash e outras coisas que so tinham pra 32-bits. Um xunxu (workaround) com bibliotecas de 32-bits resolvia o problema, mas era muito chato fazer isso.
Esse fim de semana instalei o FreeBSD 7.0 (amd64 tambem) nele, ja estava querendo tirar o Linux pra botar FreeBSD fazia um tempo. Instalou direitinho (quer dizer, deu um pouco de trabalho pra dar boot no CD).
O problema eh que o driver da nVidia pra FreeBSD suporta somente i386, ou seja, sem driver oficial pra 64-bits no FreeBSD. Ja meio triste, tentei o driver do X.org, aquele "nv" que a gente usa no xorg.conf. Nada de iniciar o X... problema viu! O jeito foi usar o X com o "vesa", que, obviamente, nao tem os recursos de aceleracao 3D.
E isso nao acontece so no mundo do UNIX nao, tambem usei Windows Vista por umas semanas nesse notebook. Instalei a versao de 64-bits e nem os proprios drivers de 64-bits que vieram no CD do computador funcionaram direito. Como resolvi? Instalei o Windows XP de 32-bits mesmo :(
Acho que vou ter que fazer o mesmo no FreeBSD ou mesmo no Linux (se tiver que voltar pra ele). Pesquisando no Google, encontrei muitas pessoas tendo problemas com SO de 64-bits: drivers faltando, menos pacotes nos repositorios, programas nao-suportados, etc.
Vamos ver no que isso vai dar.
quinta-feira, fevereiro 28, 2008
FreeBSD 7.0!
Já foi! Lançaram ontem (me atrasei a postar no blog).
Já vou baixar e deixar o CD gravado e guardadinho pras horas certas :) E vou também atualizar o servidor da RG3 que tá rodando o 7.0-RC2 ainda. Ôh, notícia boa!!!
Que o download comece!
http://www.freebsd.org/releases/7.0R/announce.html
----- texto adicionado -----
Essa não podia deixar de postar. Tenho que adicionar essa imagem a este post. Fui baixar a ISO como tinha dito acima, e vejam só: rsrs

Tá todo mundo baixando. Na lista da FUG tá uma euforia só!
Já vou baixar e deixar o CD gravado e guardadinho pras horas certas :) E vou também atualizar o servidor da RG3 que tá rodando o 7.0-RC2 ainda. Ôh, notícia boa!!!
Que o download comece!
http://www.freebsd.org/releases/7.0R/announce.html
----- texto adicionado -----
Essa não podia deixar de postar. Tenho que adicionar essa imagem a este post. Fui baixar a ISO como tinha dito acima, e vejam só: rsrs

Tá todo mundo baixando. Na lista da FUG tá uma euforia só!
segunda-feira, fevereiro 18, 2008
Flash Player para Linux 64-bits (amd64)
Muitos vão acabar chegando aqui pelo Google, achando que encontraram a solução para o Flash Player em Linux amd64. Bem, a solução completa não tenho aqui (posso até fazer um post explicando como fiz o Flash funcionar no meu Debian amd64), mas tenho a raiz da solução do problema.
Gostaria de pedir a vocês que visitassem duas páginas:
http://www.petitiononline.com/lin64swf/petition.html
http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform
A primeira, é uma petição on-line para que os desenvolvedores da Macromedia façam uma versão de 64-bits do Flash Player pra Linux. A segunda, é uma página do próprio site da Macromedia onde é possível pedir novos recursos, no caso, devemos solicitar uma versão de 64-bits do Flash Player pra Linux (foi o que eu fiz).
A expectativa é que através da petição e dos pedidos pelo site da Macromedia, eles finalmente façam uma versão de 64-bits pra Linux. Isso resolveria nossos problemas, pois não precisaríamos mais manter versões de 32-btis dos nossos navegadores pra poder ver conteúdo em Flash.
Eu por exemplo, tenho um notebook AMD64, mas preciso usar o Firefox de 32-bits por causa do Flash. Isso me deixa irritado! :P
Pois bem, vamos assinar a petição e encher o saco da Macromedia até que eles façam a bendita versão de 64-bits.
Gostaria de pedir a vocês que visitassem duas páginas:
http://www.petitiononline.com/lin64swf/petition.html
http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform
A primeira, é uma petição on-line para que os desenvolvedores da Macromedia façam uma versão de 64-bits do Flash Player pra Linux. A segunda, é uma página do próprio site da Macromedia onde é possível pedir novos recursos, no caso, devemos solicitar uma versão de 64-bits do Flash Player pra Linux (foi o que eu fiz).
A expectativa é que através da petição e dos pedidos pelo site da Macromedia, eles finalmente façam uma versão de 64-bits pra Linux. Isso resolveria nossos problemas, pois não precisaríamos mais manter versões de 32-btis dos nossos navegadores pra poder ver conteúdo em Flash.
Eu por exemplo, tenho um notebook AMD64, mas preciso usar o Firefox de 32-bits por causa do Flash. Isso me deixa irritado! :P
Pois bem, vamos assinar a petição e encher o saco da Macromedia até que eles façam a bendita versão de 64-bits.
segunda-feira, fevereiro 11, 2008
RG3.Net de cara nova
Neste último domingo, dia 10 de fevereiro, terminei a aplicação de redirecionamento da RG3.Net e fiz o upload pro servidor. Instalei tudo em uma máquina recém-formatada com FreeBSD 7.0 RC1.
O que mudou?
Absolutamente tudo!
A página principal agora tem também textos sobre o provedor de Internet a Rádio que temos aqui em Feira de Santana e uns links pra testadores de velocidade.
O site do provedor está com mais detalhes sobre o serviço e os planos de acesso e também um pequeno "how-to" explicando ao cliente como criar sua conexão com a Internet.
Mas a principal mudança foi no serviço de redirecionamento. O sistema antigo era feito em PHP e tinha algumas falhas de programação. Não vou falar muito sobre elas pra não ofender o programador antigo, que eu nem sei quem é (compramos a RG3 já pronta, não fomos nós que fundamos).
O sistema novo foi desenvolvido completamente do zero em Perl com Catalyst. Com bem menos linhas de código, escrevi uma nova aplicação com recursos a mais (mais de um domínio para escolha além de três formas de recuperação de senha) e interface gráfica melhorada.
No sistema antigo, quando o usuário fazia logon, os campos de login e senha que ficavam no menu esquerdo do site eram substituídos por três links que davam acesso às opções dos redirecionamentos. Isso era ruim, pois o usuário via a mesma página, com apenas um pequeno detalhe diferente e a maioria acreditava que não estava conseguindo fazer login, já que a página que aparecia após o "Enter" era praticamente a mesma. O que isto causava? Vários e-mails do tipo "Não consigo entrar na minha conta!!!".
O sistema novo roda também no Apache, como o antigo, porém, agora com FastCGI. Pra quem não conhece, o FastCGI permite que uma aplicação Web, no meu caso, uma aplicação em Catalyst, faça um melhor gerenciamento das requisições. Coisas comuns à aplicação, como acesso ao servidor de banco de dados, por exemplo, acontece apenas uma vez, melhorando o desempenho. No sistema em PHP, cada vez que um redirecionamento era solicitado, o programa abria uma conexão com o banco, pegava os dados e fechava a conexão. Com Catalyst no FastCGI, a conexão é aberta apenas uma vez, quando a aplicação inicia. Sempre que um redirecionamento é solicitado, a aplicação usa a conexão já aberta pra obter os dados. Diferentemente do CGI puro, onde cada requisição criava um novo processo no servidor, com FastCGI apenas um processo é criado. Em alguns momentos, quando ocorrem muitas requisições, alguns processos a mais são criados, mas ainda assim, cada processo existente gerencia várias requisições, poupando memória e recursos.
Leiam mais sobre a performance do FastCGI em http://www.fastcgi.com/devkit/doc/fcgi-perf.htm
Além dessas alterações internas no sistema e mudança de interface gráfica, quatro novos domínios foram adicionados, possibilitando outras alternativas de redirecionamentos:
A idéia é sempre adicionar novos domínios (essa tarefa ficou bem fácil na aplicação nova :D) dando mais opções pros usuários.
Já ia esquecendo, no sistema novo, apenas um login e o e-mail são solicitados na hora do cadastro. Nem o nome a gente pergunta mais. Pra que? Geralmente não colocam o nome verdadeiro mesmo :P E pensar que no sistema antigo pedia até CPF... putz!
O que mudou?
Absolutamente tudo!
A página principal agora tem também textos sobre o provedor de Internet a Rádio que temos aqui em Feira de Santana e uns links pra testadores de velocidade.
O site do provedor está com mais detalhes sobre o serviço e os planos de acesso e também um pequeno "how-to" explicando ao cliente como criar sua conexão com a Internet.
Mas a principal mudança foi no serviço de redirecionamento. O sistema antigo era feito em PHP e tinha algumas falhas de programação. Não vou falar muito sobre elas pra não ofender o programador antigo, que eu nem sei quem é (compramos a RG3 já pronta, não fomos nós que fundamos).
O sistema novo foi desenvolvido completamente do zero em Perl com Catalyst. Com bem menos linhas de código, escrevi uma nova aplicação com recursos a mais (mais de um domínio para escolha além de três formas de recuperação de senha) e interface gráfica melhorada.
No sistema antigo, quando o usuário fazia logon, os campos de login e senha que ficavam no menu esquerdo do site eram substituídos por três links que davam acesso às opções dos redirecionamentos. Isso era ruim, pois o usuário via a mesma página, com apenas um pequeno detalhe diferente e a maioria acreditava que não estava conseguindo fazer login, já que a página que aparecia após o "Enter" era praticamente a mesma. O que isto causava? Vários e-mails do tipo "Não consigo entrar na minha conta!!!".
O sistema novo roda também no Apache, como o antigo, porém, agora com FastCGI. Pra quem não conhece, o FastCGI permite que uma aplicação Web, no meu caso, uma aplicação em Catalyst, faça um melhor gerenciamento das requisições. Coisas comuns à aplicação, como acesso ao servidor de banco de dados, por exemplo, acontece apenas uma vez, melhorando o desempenho. No sistema em PHP, cada vez que um redirecionamento era solicitado, o programa abria uma conexão com o banco, pegava os dados e fechava a conexão. Com Catalyst no FastCGI, a conexão é aberta apenas uma vez, quando a aplicação inicia. Sempre que um redirecionamento é solicitado, a aplicação usa a conexão já aberta pra obter os dados. Diferentemente do CGI puro, onde cada requisição criava um novo processo no servidor, com FastCGI apenas um processo é criado. Em alguns momentos, quando ocorrem muitas requisições, alguns processos a mais são criados, mas ainda assim, cada processo existente gerencia várias requisições, poupando memória e recursos.
Leiam mais sobre a performance do FastCGI em http://www.fastcgi.com/devkit/doc/fcgi-perf.htm
Além dessas alterações internas no sistema e mudança de interface gráfica, quatro novos domínios foram adicionados, possibilitando outras alternativas de redirecionamentos:
- irg3.net
- minhapagina.info
- minhahome.com
- minhahomepage.com
A idéia é sempre adicionar novos domínios (essa tarefa ficou bem fácil na aplicação nova :D) dando mais opções pros usuários.
Já ia esquecendo, no sistema novo, apenas um login e o e-mail são solicitados na hora do cadastro. Nem o nome a gente pergunta mais. Pra que? Geralmente não colocam o nome verdadeiro mesmo :P E pensar que no sistema antigo pedia até CPF... putz!
quinta-feira, fevereiro 07, 2008
Do Red Hat para o Slackware para o Debian
Nostalgia! De vez em quando gosto de relembrar o passado e uma parte do passado do meu eterno percurso na computação que mais gosto é quando comecei a mexer com Linux (e por tabela, FreeBSD).
Tudo começou quando entrei pro curso de Física da UEFS. Peguei um trabalho voluntário pra desenvolver a home page do departamento e me botaram pra trabalhar numa estação com Red Hat 7.0. As minhas únicas tentativas com Linux até o momento foram o Corel Linux, um Linux da Corel que não foi pra frente, e o Monkey Linux, que era um mini-linux que rodava em partições FAT32 (é, isso existia!). O Monkey Linux foi minha melhor experiência com mini-linux, pois rodava tudo nele, menos o X (que na época era o XFree86), mas depois eu descobri que o problema era que o XFree86 não tinha drivers pra minha placa de vídeo da época (SiS 6202).
Com o Red Hat foi que comecei a usar Linux de verdade. Três professores (Dagoberto, Jorge Kaschny e Nazareno) me ensinavam os básicos do sistema. Kaschny era o que mais fuçava na época. Aprendi muito com eles três e mais ainda com um colega de curso, Alex Gamas, que me deu muitas dicas na época e que junto com o irmão (Leonardo Gamas), aproximadamente um ano depois, me colocaram no mundo do FreeBSD.
Os irmãos Gamas me mostraram em seguida o Slackware. Eles me conseguiram um CD do Slackware 7.0 e eu instalei o sistema em casa. Nessa época, o Windows 98 já tinha se mandado de uma vez, dando espaço pro Red Hat. Quando comecei a usar o Slackware, delirei! Adotei como o meu Linux preferido e o utilizei por muito tempo: de 2002 até 2005. Fui até o Slackware 10.
Em 2006, comecei a usar o Debian, por pressão dos amigos de Ilhéus, quando ainda cursava Ciência da Computação na UESC. O que me levou a adotar o Debian foi o tamanho do seu repositório de pacotes pré-compilados. Eu já tinha enjoado de ter que compilar tudo pra rodar no Slackware.
Fiquei usando o Debian e continuo com ele até hoje. Acredito que seja a melhor distribuição Linux existente, pois mistura a leveza e simplicidade do Slackware com a facilidade de uso do Red Hat. Não é tão seco nem tão pesado, foi o meio-termo que encontrei no mundo do Linux. Claro que pra iniciantes e leigos, o Ubuntu seria uma melhor opção, mas aí você já sai do meio-termo e tende mais para o "pesado" do Red Hat e Fedora. :P
Tudo começou quando entrei pro curso de Física da UEFS. Peguei um trabalho voluntário pra desenvolver a home page do departamento e me botaram pra trabalhar numa estação com Red Hat 7.0. As minhas únicas tentativas com Linux até o momento foram o Corel Linux, um Linux da Corel que não foi pra frente, e o Monkey Linux, que era um mini-linux que rodava em partições FAT32 (é, isso existia!). O Monkey Linux foi minha melhor experiência com mini-linux, pois rodava tudo nele, menos o X (que na época era o XFree86), mas depois eu descobri que o problema era que o XFree86 não tinha drivers pra minha placa de vídeo da época (SiS 6202).
Com o Red Hat foi que comecei a usar Linux de verdade. Três professores (Dagoberto, Jorge Kaschny e Nazareno) me ensinavam os básicos do sistema. Kaschny era o que mais fuçava na época. Aprendi muito com eles três e mais ainda com um colega de curso, Alex Gamas, que me deu muitas dicas na época e que junto com o irmão (Leonardo Gamas), aproximadamente um ano depois, me colocaram no mundo do FreeBSD.
Os irmãos Gamas me mostraram em seguida o Slackware. Eles me conseguiram um CD do Slackware 7.0 e eu instalei o sistema em casa. Nessa época, o Windows 98 já tinha se mandado de uma vez, dando espaço pro Red Hat. Quando comecei a usar o Slackware, delirei! Adotei como o meu Linux preferido e o utilizei por muito tempo: de 2002 até 2005. Fui até o Slackware 10.
Em 2006, comecei a usar o Debian, por pressão dos amigos de Ilhéus, quando ainda cursava Ciência da Computação na UESC. O que me levou a adotar o Debian foi o tamanho do seu repositório de pacotes pré-compilados. Eu já tinha enjoado de ter que compilar tudo pra rodar no Slackware.
Fiquei usando o Debian e continuo com ele até hoje. Acredito que seja a melhor distribuição Linux existente, pois mistura a leveza e simplicidade do Slackware com a facilidade de uso do Red Hat. Não é tão seco nem tão pesado, foi o meio-termo que encontrei no mundo do Linux. Claro que pra iniciantes e leigos, o Ubuntu seria uma melhor opção, mas aí você já sai do meio-termo e tende mais para o "pesado" do Red Hat e Fedora. :P
sexta-feira, novembro 23, 2007
Em breve: wxWidgets 3.0
Olá, pessoal! Quanto tempo, hein!? :P
Estive fora desde julho por falta de tempo. Vejam só:
Todo esse trabalho na RG3.Net me ocupou bastante, até o WinPolicy ficou sem atualizações. Mas as coisas estão voltando ao normal. Com o fim do curso de Ciência da Computação, vou poder configurar melhor meu tempo e o blog terá seu espaço de volta :)
Na verdade, o que eu queria dizer é que o wxWidgets 3.0 está prestes a sair. Sua principal mudança vai ser que agora, UNICODE e ANSI estarão juntos em um único build da biblioteca. Algumas classes foram melhoradas e bugs corrigidos.
Mais detalhes no wxBlog.
Estive fora desde julho por falta de tempo. Vejam só:
- Em março, tomei a frente de um provedor de Internet à Rádio em Feira de Santana, BA - RG3.Net. Além de ter que corrigir todos os erros de rede (tanto nos servidores quanto na estrutura wireless), gastei um bom tempo desenvolvendo uma aplicação Web (Perl com Catalyst) pra gerenciar o provedor (que estava meio bagunçado, tudo era feito no papel). Apenas nesse mês de novembro consegui um pouco mais de paz, pois corrigi os últimos problemas de hardware dessa rede wireless (o próximo passo é otimizá-la mais ainda).
- Estou no último semestre da Universidade, o que significa que tenho que desenvolver algo na disciplina "Estágio Supervisionado". A sorte é que usei a própria RG3.Net como meu tema de estágio, então o que faço lá tenho que escrever em um relatório e apresentar agora em dezembro.
- O site da RG3.Net também está sendo mudado (por dentro), como também os servidores. Dois deles já foram formatados e reinstalados. Lá rodava (e ainda roda) FreeBSD.
Todo esse trabalho na RG3.Net me ocupou bastante, até o WinPolicy ficou sem atualizações. Mas as coisas estão voltando ao normal. Com o fim do curso de Ciência da Computação, vou poder configurar melhor meu tempo e o blog terá seu espaço de volta :)
Na verdade, o que eu queria dizer é que o wxWidgets 3.0 está prestes a sair. Sua principal mudança vai ser que agora, UNICODE e ANSI estarão juntos em um único build da biblioteca. Algumas classes foram melhoradas e bugs corrigidos.
Mais detalhes no wxBlog.
quinta-feira, julho 12, 2007
traceroute.org e aniversário do blog
Um site interessante.
Descobri ele quando estava tendo problemas de roteamento em um dos meus servidores. Pacotes que saiam de um IP específico da minha rede não saiam do país. Além disso, ninguém fora do país conseguia enviar pacotes para esse IP. Mas outros IPs da mesma rede funcionavam OK (no final das contas, foi um filtro na Embratel que estava causando o problema).
Então, comecei a testar as rotas para esse meu IP. Primeiro, fiz um traceroute a partir de um dos servidores da Dreamhost. No traceroute, percebi que no meio do caminho, o pacote era bloqueado. Eu queria fazer mais testes, vindos de outras máquinas no exterior, mas o servidor da Dreamhost era a única máquina com acesso remoto que eu podia entrar.
Nesas buscas pelo Google, encontrei o site www.traceroute.org. A partir deste site, você pode acessar outros sites em várias partes do mundo que permitem que você faça traceroutes para qualquer IP. Com ele, pude fazer testes de traceroute a partir de máquinas em vários outros países.
Muito legal este site. Recomendo aos administradores de redes. :)
PS: Comemoremos! Hoje faz exatamente 1 ano da Casa de Just! :D
Descobri ele quando estava tendo problemas de roteamento em um dos meus servidores. Pacotes que saiam de um IP específico da minha rede não saiam do país. Além disso, ninguém fora do país conseguia enviar pacotes para esse IP. Mas outros IPs da mesma rede funcionavam OK (no final das contas, foi um filtro na Embratel que estava causando o problema).
Então, comecei a testar as rotas para esse meu IP. Primeiro, fiz um traceroute a partir de um dos servidores da Dreamhost. No traceroute, percebi que no meio do caminho, o pacote era bloqueado. Eu queria fazer mais testes, vindos de outras máquinas no exterior, mas o servidor da Dreamhost era a única máquina com acesso remoto que eu podia entrar.
Nesas buscas pelo Google, encontrei o site www.traceroute.org. A partir deste site, você pode acessar outros sites em várias partes do mundo que permitem que você faça traceroutes para qualquer IP. Com ele, pude fazer testes de traceroute a partir de máquinas em vários outros países.
Muito legal este site. Recomendo aos administradores de redes. :)
PS: Comemoremos! Hoje faz exatamente 1 ano da Casa de Just! :D
segunda-feira, julho 09, 2007
numeros.pl
Estava eu nesse fim de domingo, em casa, sem ter o que fazer. Nesse momento de ócio, lembrei de um numerólogo que estava dando entrevista essa semana na TV e procurei por Numerologia na Wikipédia. Comecei a ler o artigo e decidi fazer uns testes.
O problema é que é chato ficar somando os valores das letras dos nomes pra saber o número da pessoa. Então, como bom cientista da computação que sou, implementei um programinha pra fazer essa tarefa.
Pois bem, escrevi o código em Perl. Como programas em Perl são interpretados e não compilados, você vai precisar ter o interpretador instalado em seu computador pra executar o programa. Quem usa Windows, pode tentar o ActivePerl. Quem usa Linux ou outro UNIX, provavelmente já tem o Perl instalado (se não tiver, você pode baixar o fonte e compilar ou instalar o pacote correspondente). Pra executar o programa, use a linha de comando:
O programa irá perguntar seu nome completo e sua data de nascimento. Em seguida, vai somar os valores de cada letra do nome e dar seu número na numerologia. Depois, vai somar os números da sua data de nascimento e lhe entregar o número correspondente à sua lição de vida. Aí é só usar o artigo da Wikipédia pra saber o que cada número significa.
O problema é que é chato ficar somando os valores das letras dos nomes pra saber o número da pessoa. Então, como bom cientista da computação que sou, implementei um programinha pra fazer essa tarefa.
Pois bem, escrevi o código em Perl. Como programas em Perl são interpretados e não compilados, você vai precisar ter o interpretador instalado em seu computador pra executar o programa. Quem usa Windows, pode tentar o ActivePerl. Quem usa Linux ou outro UNIX, provavelmente já tem o Perl instalado (se não tiver, você pode baixar o fonte e compilar ou instalar o pacote correspondente). Pra executar o programa, use a linha de comando:
perl numeros.pl
O programa irá perguntar seu nome completo e sua data de nascimento. Em seguida, vai somar os valores de cada letra do nome e dar seu número na numerologia. Depois, vai somar os números da sua data de nascimento e lhe entregar o número correspondente à sua lição de vida. Aí é só usar o artigo da Wikipédia pra saber o que cada número significa.
#!/usr/bin/perl
# Referencia: http://pt.wikipedia.org/wiki/Numerologia
# Soma os digitos
sub soma {
my $numero = 0;
my (@digitos) = split(//, $_[0]);
for (my $i = 0; $i < @digitos; ++$i) {
$numero += abs($digitos[$i]);
}
if ($numero >= 10) {
return &soma($numero);
} else {
return $numero;
}
}
# Tabela de numerologia
my $tabela = ({
a => 1, b => 2, c => 3, d => 4, e => 5, f => 6,
g => 7, h => 8, i => 9, j => 1, k => 2, l => 3,
m => 4, n => 5, o => 6, p => 7, q => 8, r => 9,
s => 1, t => 2, u => 3, v => 4, w => 5, x => 6,
y => 7, z => 8,
});
# Solicita o nome
my $nome = undef;
do {
print "Digite seu nome completo, sem acentos ou cedilha:\n";
$nome = lc(<STDIN>);
chop($nome);
} while ($nome eq '');
# Solicida data de nascimento
my $nasc = undef;
do {
print "Digite sua data de nascimento, ex.: 10\/11\/1982\n";
$nasc = lc(<STDIN>);
chop($nasc);
} while ($nasc eq '');
# Divide as letras e calcula a soma
my (@letras) = split(//, $nome);
my $numero = 0;
for (my $i = 0; $i < @letras; ++$i) {
next if $letras[$i] eq ' ';
$numero += $tabela->{$letras[$i]};
}
# Exibe o resultado
print "Seu numero: " . &soma($numero) . "\n";
print "Sua licao de vida: " . &soma($nasc) . "\n";
sábado, julho 07, 2007
Novo: Slackware 12
Isso aqui vai acabar virando blog de notícias de atualização de distros :P Mas pelo menos tô voltando à ativa, rsrs
Pois bem, o Slackware 12 veio essa semana e algumas mudanças são notáveis. De acordo com o anúncio oficial, o Slackware agora vem com dois tipos de kernels: kernels grandes, que vêm com todo tipo de driver possível, geralmente pra facilitar a instalação do sistema, além do kernel genérico, que tem os drivers compilados como módulo (a forma mais comum de kernel).
Outra novidade é que ele agora vem com o HAL (Hardware Abstraction Layer), aumentando a habilidade Plug and Play do Slackware.
A nova versão atualiza também a maioria dos pacotes: kernel 2.6.21.5, KDE 3.5.7, X.Org 7.2.0, gcc 4.1.2, Apache 2.2.4, etc.
Para a lista completa das mudanças, leiam o anúncio oficial.
Pois bem, o Slackware 12 veio essa semana e algumas mudanças são notáveis. De acordo com o anúncio oficial, o Slackware agora vem com dois tipos de kernels: kernels grandes, que vêm com todo tipo de driver possível, geralmente pra facilitar a instalação do sistema, além do kernel genérico, que tem os drivers compilados como módulo (a forma mais comum de kernel).
Outra novidade é que ele agora vem com o HAL (Hardware Abstraction Layer), aumentando a habilidade Plug and Play do Slackware.
A nova versão atualiza também a maioria dos pacotes: kernel 2.6.21.5, KDE 3.5.7, X.Org 7.2.0, gcc 4.1.2, Apache 2.2.4, etc.
Para a lista completa das mudanças, leiam o anúncio oficial.
domingo, abril 08, 2007
Debian 4.0 (etch) se torna stable!
Finalmente! Aguardava esse momento há alguns meses.
O Debian 4.0, codenome etch, deixou de ser testing e agora é stable. Ele havia sido congelado em dezembro do ano passado, ou seja, novos pacotes deixaram de ser adicionados e os pacotes já contidos no sistema estavam em fase de correção de bugs.
A notícia oficial pode ser lida no site do Debian:
http://www.debian.org/News/2007/20070408
Como também, instruções de download e instalação:
http://www.debian.org/distrib/
Quem usa o Justsoft GNU/Linux, já está rodando o sistema Justsoft em cima do Debian etch. Portanto, basta atualizar o sistema através do APT ou do próprio assistente de atualização que fica ao lado do relógio do GNOME.
Apesar de agora ser stable, vou esperar um pouco antes de atualizar meu servidor, que já usa Debian 3.1 (sarge).
O Debian 4.0, codenome etch, deixou de ser testing e agora é stable. Ele havia sido congelado em dezembro do ano passado, ou seja, novos pacotes deixaram de ser adicionados e os pacotes já contidos no sistema estavam em fase de correção de bugs.
A notícia oficial pode ser lida no site do Debian:
http://www.debian.org/News/2007/20070408
Como também, instruções de download e instalação:
http://www.debian.org/distrib/
Quem usa o Justsoft GNU/Linux, já está rodando o sistema Justsoft em cima do Debian etch. Portanto, basta atualizar o sistema através do APT ou do próprio assistente de atualização que fica ao lado do relógio do GNOME.
Apesar de agora ser stable, vou esperar um pouco antes de atualizar meu servidor, que já usa Debian 3.1 (sarge).
domingo, março 18, 2007
Curso de wxWidgets, post 14: Comunicando-se pela rede
Olá, pessoal! Como havia prometido no post anterior, este será sobre sockets e comunicação via rede.
Nesta primeira parte, abordarei o cliente, ou seja, o programa irá conectar em algum servidor. Tive a idéia de fazer um código para enviar e-mails, já que o protocolo SMTP é simples e fácil para mensagens em texto plano e sem anexos. Para quem não conhece o protocolo SMTP, sugiro que leia a RFC822, que descreve seu formato:
ftp://ftp.rfc-editor.org/in-notes/rfc822.txt
De qualquer forma, vou dar uma resumida no protocolo.
Nos parágrafos abaixo, <- indica uma mensagem que está vindo do servidor e -> indica uma mensagem que o cliente está enviando para o servidor.
Ao se conectar em um servidor SMTP, o cliente recebe uma mensagem de boas-vindas, geralmente com o endereço do servidor e alguns dados do software:
Em seguida, o cliente deve se idenficar enviando a string "EHLO" e o seu endereço. Após a identificação, o servidor dá algumas informações sobre o envio da mensagem (não relevante para nós no momento):
Agora o cliente deve dizer o endereço do remetente com o comando "MAIL From:" e do destinatário com "RCPT To:":
Após estas informações, o cliente começa a mensagem com o comando "DATA":
O fim da mensagem deve ser indicado com um ponto (.) sozinho em uma linha. Por último, o cliente pede para o servidor fechar a conexão com "QUIT":
E é isto! Você pode testar os comandos conectando em algum servidor SMTP pelo telnet. Basta executar o comando "telnet mx1.hotmail.com 25" para conectar no servidor SMTP do Hotmail e enviar mensagens para endereços de lá. Veja abaixo uma pequena lista com o servidor SMTP de alguns serviços de e-mail famosos:
Se você usa Linux ou algum outro UNIX, use o comando host para saber o servidor SMTP de algum domínio de e-mail. Por exemplo, para saber o servidor SMTP de gmail.com:
Voltando à programação, o que iremos fazer é um programa em wxWidgets para se conectar a um servidor SMTP e enviar um e-mail.
A parte wxWidgets da coisa
Para todo o trabalho de rede no wxWidgets, usaremos a classe wxSocketBase e uma classe derivada, a wxSocketClient.
wxSocketBase é a classe base para todas as outras classes de socket no wxWidgets. Neste post, usaremos apenas a classe wxSocketClient, que é responsável por fazer as conexões do nosso programa, que é o cliente, no servidor.
Conectando-se no servidor
Antes de fazer alguma conexão com a wxSocketClient, precisamos do endereço do servidor ao qual vamos nos conectar e também a porta da conexão. Para manusear essas informações, usaremos a classe wxIPV4address. Essa classe serve para guardar informações de um endereço, como número IP e porta. Para definir o endereço do servidor e a porta, usamos dois métodos:
No trecho de código acima, criamos um objeto de nome host, que é uma instância de wxIPV4address. Em seguida, definimos o endereço como smtp.server.com e a porta como 25.
Após criar um objeto com o endereço e a porta do servidor, podemos chamar o método wxSocketClient::Connect() para conectar no servidor:
Se a conexão for feita com sucesso, o método retorna true, que será guardado na variável status. Em caso de erro na conexão, logicamente, o método retornará false.
Por padrão, o método wxSocketClient::Connect() aguarda a conexão ser feita ou a ocorrência de um erro para prosseguir a execução. Mas é possível chamar o método e continuar a execução do programa enquanto o socket está se conectando, basta adicionar um parâmetro ao método:
O segundo parâmetro indica se o método deverá aguardar a conexão ser completada. Se você escolheu esta maneira para se conectar, poderá verificar se a conexão foi feita posteriormente com o método wxSocketBase::IsConnected() ou até mesmo, aguardar pela conexão em um ponto posterior com wxSocketClient::WaitOnConnect().
Enviando dados
Após ter sido feita a conexão, já é possível enviar e receber dados. Para fazer o envio, usamos o método wxSocketBase::Write(). Após enviar qualquer dado, podemos verificar se o envio foi feito com sucesso com o método wxSocketBase::Error():
No trecho acima, enviamos a string "EHLO localhost\r\n" e em caso de erro, uma mensagem é exibida ao usuário. Perceba o cast (char *) e o método wxString::mb_str(). Este método retorna a string no formato ANSI. Perceba também que o método wxSocketBase::Write() não define um tipo de dado específico, você pode enviar texto puro ou binário. Como no nosso exemplo de um cliente SMTP estamos enviando texto puro, obtemos o formato ANSI da string e usamos o cast (char *) para indicar ao método que estamos enviando um char. O segundo parâmetro do método indica o tamanho do dado que estamos enviando. No caso, como é texto puro em ANSI (1 byte por caracter), indicamos o tamanho da string.
Em caso de erro no envio, wxSocketBase::Error() retorna true.
Recebendo dados
Após enviar algum dado pelo socket, geralmente esperamos por uma resposta, esta é a hora de fazer a leitura do socket. Para isto, usaremos o método wxSocketBase::Read():
Primeiro, criamos um buffer do tipo char com 1 KB. Em seguida, fazemos a leitura, armazenando a saída em buffer e indicando o máximo de dados que deverá ser lido (subtraímos 1 do tamanho pois devemos guardar um espaço para o terminador de string \0 da variável).
Mais uma vez, wxSocketBase::Error() entra em ação para nos informar se houve algum erro.
Neste trecho, usamos também o método wxSocketBase::LastCount(), ele retorna o número de bytes lidos no wxSocketBase::Read(). Ele também pode ser usado após um wxSocketBase::Write() para saber quantos bytes foram enviados de fato.
Fechando a conexão
Após enviarmos e recebermos todos os dados necessários para a conexão, devemos terminá-la. Basta um único método para isso, o wxSocketBase::Close():
Existe também um outro método relacionado ao término de conexão, o wxSocketBase::WaitForLost(). Com ele, você pode indicar um timeout em segundos ou milissegundos. Se a conexão for fechada antes do timeout (o servidor pode fechar a conexão), o método retorna true, caso o timeout seja atingido, ele retorna false.
Outras formas de E/S
Além do wxSocketBase::Read() e do wxSocketBase::Write(), existem também o wxSocketBase::WriteMsg() e o wxSocketBase::ReadMsg(). Com esses dois métodos, é possível trocar mensagens entre duas aplicações em wxWidgets sem precisar se preocupar com a contagem de bytes enviados ou recebidos.
Mostrarei estes e outros métodos das classes de socket em posts futuros. Ainda há muito o que falar sobre sockets no wxWidgets :)
Configurando o socket
Também é possível fazer algumas configurações no socket antes de utilizá-lo. Veja abaixo.
wxSocketBase::SetTimeout(): configura o tempo de timeout em segundos para os métodos de E/S e de espera do socket. O valor padrão é de 10 minutos.
wxSocketBase::SetFlags(): configura o comportamento de espera do socket nas operações de E/S. Pode receber como argumento os valores abaixo:
wxSOCKET_NONE: Funcionamento normal.
wxSOCKET_NOWAIT: Lê ou grava o máximo possível de dados e retorna imediatamente.
wxSOCKET_WAITALL: Aguarda que todo o dado seja lido ou gravado ou que um erro ocorra para retornar.
wxSOCKET_BLOCK: Bloqueia a interface gráfica durante a operação.
wxSOCKET_REUSEADDR: Permite que o socket escute em uma porta que já está em uso (apenas para sockets de servidor).
Para configurar o socket para sempre aguardar que os dados sejam lidos ou gravados por completo antes de continuar a execução do código, use:
Outros métodos de configuração do socket serão vistos nos outros posts.
Nosso código de exemplo
Finalmente, o código do programa que irá fazer a conexão e enviar o e-mail. O código está bem documentado para que você possa entender cada parte do programa.
A interface gráfica já vai aparecer preenchida com os dados do servidor SMTP do GMail e meu endereço de e-mail de lá. Por favor, envie um e-mail para mim pelo programa de exemplo :) Obrigado.
Nesta primeira parte, abordarei o cliente, ou seja, o programa irá conectar em algum servidor. Tive a idéia de fazer um código para enviar e-mails, já que o protocolo SMTP é simples e fácil para mensagens em texto plano e sem anexos. Para quem não conhece o protocolo SMTP, sugiro que leia a RFC822, que descreve seu formato:
ftp://ftp.rfc-editor.org/in-notes/rfc822.txt
De qualquer forma, vou dar uma resumida no protocolo.
Nos parágrafos abaixo, <- indica uma mensagem que está vindo do servidor e -> indica uma mensagem que o cliente está enviando para o servidor.
Ao se conectar em um servidor SMTP, o cliente recebe uma mensagem de boas-vindas, geralmente com o endereço do servidor e alguns dados do software:
<- 220 spaceymail-mx1.g.dreamhost.com ESMTP
Em seguida, o cliente deve se idenficar enviando a string "EHLO" e o seu endereço. Após a identificação, o servidor dá algumas informações sobre o envio da mensagem (não relevante para nós no momento):
-> EHLO just.justsoft.com.br
<- 250-spaceymail-mx1.g.dreamhost.com
<- 250-PIPELINING
<- 250-SIZE 40960000
<- 250-ETRN
<- 250-STARTTLS
<- 250 8BITMIME
Agora o cliente deve dizer o endereço do remetente com o comando "MAIL From:" e do destinatário com "RCPT To:":
-> MAIL From: <teste@teste.com>
<- 250 Ok
-> RCPT To: <jpjust@justsoft.com.br>
<- 250 Ok
Após estas informações, o cliente começa a mensagem com o comando "DATA":
-> DATA
<- 354 End data with <CR><LF>.<CR><LF>
-> From: <just@just.com>
-> To: <jpjust@justsoft.com.br>
-> Date, Thu, 15 Mar 2007 21:00:00 +0000
-> Subject: Teste
->
-> teste
->
-> .
<- 250 Ok: queued as 6C0C3CE937
O fim da mensagem deve ser indicado com um ponto (.) sozinho em uma linha. Por último, o cliente pede para o servidor fechar a conexão com "QUIT":
-> QUIT
<- 221 Bye
E é isto! Você pode testar os comandos conectando em algum servidor SMTP pelo telnet. Basta executar o comando "telnet mx1.hotmail.com 25" para conectar no servidor SMTP do Hotmail e enviar mensagens para endereços de lá. Veja abaixo uma pequena lista com o servidor SMTP de alguns serviços de e-mail famosos:
Hotmail: mx1.hotmail.com
Yahoo!: a.mx.mail.yahoo.com
GMail: gmail-smtp-in.l.google.com
UOL: mx.uol.com.br
BOL: mx.boil.com.br
Se você usa Linux ou algum outro UNIX, use o comando host para saber o servidor SMTP de algum domínio de e-mail. Por exemplo, para saber o servidor SMTP de gmail.com:
$ host -t MX gmail.com
Voltando à programação, o que iremos fazer é um programa em wxWidgets para se conectar a um servidor SMTP e enviar um e-mail.
A parte wxWidgets da coisa
Para todo o trabalho de rede no wxWidgets, usaremos a classe wxSocketBase e uma classe derivada, a wxSocketClient.
wxSocketBase é a classe base para todas as outras classes de socket no wxWidgets. Neste post, usaremos apenas a classe wxSocketClient, que é responsável por fazer as conexões do nosso programa, que é o cliente, no servidor.
Conectando-se no servidor
Antes de fazer alguma conexão com a wxSocketClient, precisamos do endereço do servidor ao qual vamos nos conectar e também a porta da conexão. Para manusear essas informações, usaremos a classe wxIPV4address. Essa classe serve para guardar informações de um endereço, como número IP e porta. Para definir o endereço do servidor e a porta, usamos dois métodos:
wxIPV4address host;
host.Hostname(wxT("smtp.server.com"));
host.Service(wxT("25"));
No trecho de código acima, criamos um objeto de nome host, que é uma instância de wxIPV4address. Em seguida, definimos o endereço como smtp.server.com e a porta como 25.
Após criar um objeto com o endereço e a porta do servidor, podemos chamar o método wxSocketClient::Connect() para conectar no servidor:
wxSocketClient sock;
bool status;
status = sock.Connect(host);
Se a conexão for feita com sucesso, o método retorna true, que será guardado na variável status. Em caso de erro na conexão, logicamente, o método retornará false.
Por padrão, o método wxSocketClient::Connect() aguarda a conexão ser feita ou a ocorrência de um erro para prosseguir a execução. Mas é possível chamar o método e continuar a execução do programa enquanto o socket está se conectando, basta adicionar um parâmetro ao método:
sock.Connect(host, false);
O segundo parâmetro indica se o método deverá aguardar a conexão ser completada. Se você escolheu esta maneira para se conectar, poderá verificar se a conexão foi feita posteriormente com o método wxSocketBase::IsConnected() ou até mesmo, aguardar pela conexão em um ponto posterior com wxSocketClient::WaitOnConnect().
Enviando dados
Após ter sido feita a conexão, já é possível enviar e receber dados. Para fazer o envio, usamos o método wxSocketBase::Write(). Após enviar qualquer dado, podemos verificar se o envio foi feito com sucesso com o método wxSocketBase::Error():
wxString dado = wxT("EHLO localhost\r\n");
socket.Write((char *)dado.mb_str(), dado.Len());
if (socket.Error())
{
wxMessageBox(wxT("Erro ao enviar o dado."));
}No trecho acima, enviamos a string "EHLO localhost\r\n" e em caso de erro, uma mensagem é exibida ao usuário. Perceba o cast (char *) e o método wxString::mb_str(). Este método retorna a string no formato ANSI. Perceba também que o método wxSocketBase::Write() não define um tipo de dado específico, você pode enviar texto puro ou binário. Como no nosso exemplo de um cliente SMTP estamos enviando texto puro, obtemos o formato ANSI da string e usamos o cast (char *) para indicar ao método que estamos enviando um char. O segundo parâmetro do método indica o tamanho do dado que estamos enviando. No caso, como é texto puro em ANSI (1 byte por caracter), indicamos o tamanho da string.
Em caso de erro no envio, wxSocketBase::Error() retorna true.
Recebendo dados
Após enviar algum dado pelo socket, geralmente esperamos por uma resposta, esta é a hora de fazer a leitura do socket. Para isto, usaremos o método wxSocketBase::Read():
char buffer[1024] = {0};
socket.Read(buffer, 1024 - 1);
if (socket.Error())
{
wxMessageBox(wxT("Erro ao fazer a leitura."));
}
int contagem = socket.LastCount();Primeiro, criamos um buffer do tipo char com 1 KB. Em seguida, fazemos a leitura, armazenando a saída em buffer e indicando o máximo de dados que deverá ser lido (subtraímos 1 do tamanho pois devemos guardar um espaço para o terminador de string \0 da variável).
Mais uma vez, wxSocketBase::Error() entra em ação para nos informar se houve algum erro.
Neste trecho, usamos também o método wxSocketBase::LastCount(), ele retorna o número de bytes lidos no wxSocketBase::Read(). Ele também pode ser usado após um wxSocketBase::Write() para saber quantos bytes foram enviados de fato.
Fechando a conexão
Após enviarmos e recebermos todos os dados necessários para a conexão, devemos terminá-la. Basta um único método para isso, o wxSocketBase::Close():
socket.Close()
Existe também um outro método relacionado ao término de conexão, o wxSocketBase::WaitForLost(). Com ele, você pode indicar um timeout em segundos ou milissegundos. Se a conexão for fechada antes do timeout (o servidor pode fechar a conexão), o método retorna true, caso o timeout seja atingido, ele retorna false.
Outras formas de E/S
Além do wxSocketBase::Read() e do wxSocketBase::Write(), existem também o wxSocketBase::WriteMsg() e o wxSocketBase::ReadMsg(). Com esses dois métodos, é possível trocar mensagens entre duas aplicações em wxWidgets sem precisar se preocupar com a contagem de bytes enviados ou recebidos.
Mostrarei estes e outros métodos das classes de socket em posts futuros. Ainda há muito o que falar sobre sockets no wxWidgets :)
Configurando o socket
Também é possível fazer algumas configurações no socket antes de utilizá-lo. Veja abaixo.
wxSocketBase::SetTimeout(): configura o tempo de timeout em segundos para os métodos de E/S e de espera do socket. O valor padrão é de 10 minutos.
socket.SetTimeout(120); // Configura o timeout para 120 segundos
wxSocketBase::SetFlags(): configura o comportamento de espera do socket nas operações de E/S. Pode receber como argumento os valores abaixo:
wxSOCKET_NONE: Funcionamento normal.
wxSOCKET_NOWAIT: Lê ou grava o máximo possível de dados e retorna imediatamente.
wxSOCKET_WAITALL: Aguarda que todo o dado seja lido ou gravado ou que um erro ocorra para retornar.
wxSOCKET_BLOCK: Bloqueia a interface gráfica durante a operação.
wxSOCKET_REUSEADDR: Permite que o socket escute em uma porta que já está em uso (apenas para sockets de servidor).
Para configurar o socket para sempre aguardar que os dados sejam lidos ou gravados por completo antes de continuar a execução do código, use:
socket.SetFlags(wxSOCKET_WAITALL);
Outros métodos de configuração do socket serão vistos nos outros posts.
Nosso código de exemplo
Finalmente, o código do programa que irá fazer a conexão e enviar o e-mail. O código está bem documentado para que você possa entender cada parte do programa.
A interface gráfica já vai aparecer preenchida com os dados do servidor SMTP do GMail e meu endereço de e-mail de lá. Por favor, envie um e-mail para mim pelo programa de exemplo :) Obrigado.
/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Enviando e-mails via SMTP
*
* O objetivo deste código-fonte é demonstrar diversas classes
* ensinadas no curso de wxWidgets do blog "A Casa de Just".
*
* As aulas do curso de wxWidgets podem ser encontradas em forma
* de posts no blog: http://jpjust.blogspot.com
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 18 de março de 2007, 00:48, Ilhéus, BA, Brasil.
*/
#include <wx/wx.h>
#include <wx/socket.h>
#include <string.h>
#include <time.h>
// Tamanho do buffer que será utilizado no recebimento de mensagens
#define BUFFER 256
// Enumeração dos IDs
enum
{
ID_ENVIAR
};
// Classe: MailApp
class MailApp: public wxApp
{
public:
virtual bool OnInit();
};
// Classe: MailFrame
class MailFrame: public wxFrame
{
public:
MailFrame(void);
DECLARE_EVENT_TABLE()
private:
void EnviarMensagem(wxCommandEvent &event); // Método para enviar a mensagem
wxString Envia(wxSocketBase *socket, wxString msg); // Método para enviar dados pelo socket
wxString Le(wxSocketBase *socket); // Método para obter dados no socket
wxStaticText *lb_servidor;
wxStaticText *lb_porta;
wxStaticText *lb_de;
wxStaticText *lb_para;
wxStaticText *lb_assunto;
wxTextCtrl *txt_servidor;
wxTextCtrl *txt_porta;
wxTextCtrl *txt_de;
wxTextCtrl *txt_para;
wxTextCtrl *txt_assunto;
wxTextCtrl *txt_mensagem;
wxTextCtrl *txt_proto;
wxButton *btn_enviar;
};
// Tabela de eventos
BEGIN_EVENT_TABLE(MailFrame, wxFrame)
EVT_BUTTON(ID_ENVIAR, MailFrame::EnviarMensagem)
END_EVENT_TABLE()
// Método: MailApp::OnInit()
// Inicialização do programa
bool MailApp::OnInit()
{
MailFrame *frame = new MailFrame();
frame->Show();
return true;
}
// Método: MailFrame::MailFrame
// Construtor do frame
MailFrame::MailFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Enviar e-mail - http://jpjust.blogspot.com"))
{
//wxMessageBox(wxNow());
// Sizers
wxGridSizer *sizer_g = new wxGridSizer(5, 2, 0, 0);
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);
// Texto indicativo
lb_servidor = new wxStaticText(this, wxID_ANY, wxT("Servidor SMTP:"));
lb_porta = new wxStaticText(this, wxID_ANY, wxT("Porta:"));
lb_de = new wxStaticText(this, wxID_ANY, wxT("De:"));
lb_para = new wxStaticText(this, wxID_ANY, wxT("Para:"));
lb_assunto = new wxStaticText(this, wxID_ANY, wxT("Assunto:"));
// Caixas de texto
txt_servidor = new wxTextCtrl(this, wxID_ANY, wxT("gmail-smtp-in.l.google.com"), wxDefaultPosition, wxSize(200, -1));
txt_porta = new wxTextCtrl(this, wxID_ANY, wxT("25"));
txt_de = new wxTextCtrl(this, wxID_ANY, wxT("seu@email.com"), wxDefaultPosition, wxSize(200, -1));
txt_para = new wxTextCtrl(this, wxID_ANY, wxT("just1982@gmail.com"), wxDefaultPosition, wxSize(200, -1));
txt_assunto = new wxTextCtrl(this, wxID_ANY, wxT("Post 14"), wxDefaultPosition, wxSize(200, -1));
txt_mensagem = new wxTextCtrl(this, wxID_ANY, wxT("Eu li o post 14!"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_WORDWRAP);
txt_proto = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_WORDWRAP | wxTE_READONLY);
// Botão de enviar
btn_enviar = new wxButton(this, ID_ENVIAR, wxT("Enviar"));
// Adiciona itens nos sizers
sizer_g->Add(lb_servidor, 0, wxALL, 5);
sizer_g->Add(txt_servidor, 0, wxALL, 5);
sizer_g->Add(lb_porta, 0, wxALL, 5);
sizer_g->Add(txt_porta, 0, wxALL, 5);
sizer_g->Add(lb_de, 0, wxALL, 5);
sizer_g->Add(txt_de, 0, wxALL, 5);
sizer_g->Add(lb_para, 0, wxALL, 5);
sizer_g->Add(txt_para, 0, wxALL, 5);
sizer_g->Add(lb_assunto, 0, wxALL, 5);
sizer_g->Add(txt_assunto, 0, wxALL, 5);
sizer_v->Add(sizer_g, 0, wxALL, 0);
sizer_v->Add(txt_mensagem, 2, wxALL | wxEXPAND, 5);
sizer_v->Add(txt_proto, 1, wxALL | wxEXPAND, 5);
sizer_v->Add(btn_enviar, 0, wxALL | wxALIGN_RIGHT, 5);
SetSizerAndFit(sizer_v);
}
/////////////////////////////////////////////////
// A partir daqui, a interface gráfica já está criada e
// veremos os métodos que realmente importam neste exemplo.
// Método: Envia
// Envia 'msg' para o socket e efetua a leitura logo em seguida, retornando o resultado
wxString MailFrame::Envia(wxSocketBase *socket, wxString msg)
{
// Se estiver desconectado, sai do método e retorna uma string vazia
if (socket->IsDisconnected())
return wxEmptyString;
wxString res;
// Envia 'msg' pelo socket
socket->Write((char *)msg.mb_str(), msg.Len());
// Em caso de erro, retorna uma mensagem avisando e fecha a conexão
if (socket->Error())
{
return wxT(">> Ocorreu um erro ao se comunicar com o servidor!\n");
socket->Close();
}
// Recebe a resposta enviada pelo outro host e a retorna
return msg + Le(socket);
}
// Método: Le
// Lê o conteúdo do socket (ou seja, qualquer mensagem enviada pelo outro host)
wxString MailFrame::Le(wxSocketBase *socket)
{
wxString res;
char buf[BUFFER]; // Buffer para recebimento
do
{
memset(buf, 0, BUFFER);
socket->Read(buf, BUFFER - 1); // Faz a leitura e armazena no buffer
res.Append(buf);
// Enquanto 'res' estiver vazio (nenhuma leitura foi feita ainda) ou
// enquanto houver dados para serem lidos, continuaremos percorrendo o laço
} while ((socket->LastCount() > 0) || (res.Len() == 0));
return res;
}
// Método: MailFrame::Envia
// Envia o e-mail
// Este método vai fazer a conexão, enviar os dados e fechar a conexão
void MailFrame::EnviarMensagem(wxCommandEvent &event)
{
wxIPV4address host;
wxSocketClient sock;
wxString msg, saida;
// Obtém a hora no formato requerido pela RFC822
// O formato é "Dia, data mês ano hora fuso"
// Ex.: Thu, 15 Mar 2007 20:19:00 BRT
char hora[50] = {0};
time_t now = time(NULL);
strftime(hora, 50, "%a, %d %b %Y %T %Z", localtime(&now));
// Configura o objeto 'host'
// Aqui definimos o endereço do servidor e a porta
host.Hostname(txt_servidor->GetValue());
host.Service(txt_porta->GetValue());
// Configuração do socket
// O timeout padrão para operações de E/S será de 120 segundos
// A flag 'wxSOCKET_NOWAIT' indica que operações de E/S irão retornar imediatamente
// (com esta flag, o programa não irá ficar parado em um Read() ou Write() do socket)
sock.SetTimeout(120);
sock.SetFlags(wxSOCKET_NOWAIT);
txt_proto->AppendText(wxT(">> Tentando se conectar...\n"));
if (sock.Connect(host) == false)
{
// Erro na conexão
txt_proto->AppendText(wxT(">> Ocorreu um erro ao tentar conectar no servidor!\n"));
return;
}
txt_proto->AppendText(wxT(">> Conectado!\n"));
txt_proto->AppendText(Le(&sock)); // Lê a mensagem de boas-vindas do servidor
// Neste bloco, enviamos uma identificação (EHLO), o remetente (MAIL From),
// o destinatário (RCPT To) e indicamos o início da mensagem (DATA)
txt_proto->AppendText(Envia(&sock, wxT("EHLO ") + wxGetFullHostName() + wxT("\r\n")));
txt_proto->AppendText(Envia(&sock, wxT("MAIL From: <") + txt_de->GetValue() + wxT(">\r\n")));
txt_proto->AppendText(Envia(&sock, wxT("RCPT To: <") + txt_para->GetValue() + wxT(">\r\n")));
txt_proto->AppendText(Envia(&sock, wxT("DATA\r\n")));
// Agora, o e-mail será montado. O corpo do e-mail tem o seguinte formato:
//
// From: "Nome do remetente" <email_do_remetente>
// To: "Nome do destinatário" <email_do_destinatário>
// Date: Data de envio (obedecendo a RFC822)
// Subject: Assunto do e-mail
//
// Mensagem, linha 1...
// Mensagem, linha 2...
//
// . (deve conter um ponto na última linha para indicar o fim da mensagem)
msg.Clear();
msg.Append(wxT("From: <") + txt_de->GetValue() + wxT(">\r\n"));
msg.Append(wxT("To: <") + txt_para->GetValue() + wxT(">\r\n"));
msg.Append(wxT("Date: ") + wxString(hora) + wxT("\r\n"));
msg.Append(wxT("Subject: ") + txt_assunto->GetValue() + wxT("\r\n\r\n"));
msg.Append(txt_mensagem->GetValue() + wxT("\r\n\r\n"));
msg.Append(wxT("--\r\nVisite A Casa de Just: http://jpjust.blogspot.com\r\n"));
msg.Append(wxT("\r\n.\r\n"));
// O corpo do e-mail é enviado pelo socket e a resposta do servidor é
// inserida na caixa de texto
txt_proto->AppendText(Envia(&sock, msg));
// Por último, fechamos a conexão com o comando QUIT
txt_proto->AppendText(Envia(&sock, wxT("QUIT\r\n")));
// Aguarda que a conexão seja fechada pelo servidor
if (sock.WaitForLost(120) == false)
{
txt_proto->AppendText(wxT(">> Erro ao enviar mensagem!\n"));
}
else
{
txt_proto->AppendText(wxT(">> Mensagem enviada!\n"));
}
// Pronto! O e-mail está enviado! :)
}
IMPLEMENT_APP(MailApp)
quinta-feira, março 08, 2007
Notícias do Blog
Olá, pessoal!
O curso de wxWidgets irá voltar ao andamento normal na próxima semana, pois nestes últimos dias, estive (e ainda estou) fora para resolver pendências. Na volta do curso, postarei sobre comunicação em rede com sockets.
Estive também estudando sobre como usar banco de dados com wxWidgets e postarei sobre isso assim que estiver por dentro do assunto.
E falando em banco de dados, um leitor do blog chamado Guilherme sugeriu o uso da biblioteca SQLAPI++ para acesso a banco de dados com C++. Estive olhando os códigos de exemplo e parece ser bem melhor que as classes do wxWidgets (postarei outro dia sobre o que estou achando do acesso a banco de dados no wxWidgets). Pena que não é gratuita, custa US$ 249,00.
Se alguém conhecer alguma outra alternativa para acesso a banco de dados com C/C++, escreva um comentário. :)
Até o próximo post!
O curso de wxWidgets irá voltar ao andamento normal na próxima semana, pois nestes últimos dias, estive (e ainda estou) fora para resolver pendências. Na volta do curso, postarei sobre comunicação em rede com sockets.
Estive também estudando sobre como usar banco de dados com wxWidgets e postarei sobre isso assim que estiver por dentro do assunto.
E falando em banco de dados, um leitor do blog chamado Guilherme sugeriu o uso da biblioteca SQLAPI++ para acesso a banco de dados com C++. Estive olhando os códigos de exemplo e parece ser bem melhor que as classes do wxWidgets (postarei outro dia sobre o que estou achando do acesso a banco de dados no wxWidgets). Pena que não é gratuita, custa US$ 249,00.
Se alguém conhecer alguma outra alternativa para acesso a banco de dados com C/C++, escreva um comentário. :)
Até o próximo post!
quarta-feira, fevereiro 07, 2007
Curso de wxWidgets, post 13: Formatando texto
Para finalizar o editor de textos, vamos adicionar formatação a ele. Para isto, irei usar uma função que já vimos no curso: wxGetFontFromUser().
Primeiro, vamos incluir o cabeçalho da função:
Vamos também criar um novo método para a formatação. Este método irá se chamar MeuFrame::Formatar(). Vamos declarar a nova função na definição da classe:
E agora, implementemos o método:
Primeiro, o método tenta obter a formatação atual do texto selecionado (wxTextCtrl::GetStyle() não é suportado em todas as plataformas, testei no Linux e não funcionou). Após obter a formatação, iremos utilizá-la em wxGetFontFromUser() para inicializar os valores da janela, assim, sempre a janela de formatação for aberta, ela estará configurada com a formatação atual.
Em seguida, wxGetFontFromUser() retorna a nova formatação e podemos aplicá-la ao texto selecionado.
Agora devemos criar um botão na barra de ferramentas para este método. Vamos adicionar uma ID para este botão:
E criamos o novo botão no construtor de MeuFrame:
Pronto! Está feito. :)

Próximo passo
O editor de textos pára por aqui. Estou querendo falar sobre sockets no próximo post, mas precisarei elaborar um texto maior, pois tem bastante coisa pra explicar. Se alguém quiser aprender algo específico do wxWidgets, postem nos comentários. Assim vocês me ajudam a escolher o próximo assunto. :)
Como sempre faço, o código-fonte completo está abaixo:
Primeiro, vamos incluir o cabeçalho da função:
#include <wx/fontdlg.h>
Vamos também criar um novo método para a formatação. Este método irá se chamar MeuFrame::Formatar(). Vamos declarar a nova função na definição da classe:
class MeuFrame: public wxFrame
{
...
private:
...
void Formatar(void);
}
E agora, implementemos o método:
// Formatação
void MeuFrame::Formatar(void)
{
long inicio, fim;
wxTextAttr attr;
wxFont font;
// Obtém a formatação atual (não suportado em todas as plataformas)
txt_file->GetSelection(&inicio, &fim);
txt_file->GetStyle(inicio, attr);
font = attr.GetFont();
// Altera a formatação
font = wxGetFontFromUser(this, font);
attr.SetFont(font);
txt_file->SetStyle(inicio, fim, attr); // Aplica o estilo ao texto
}
Primeiro, o método tenta obter a formatação atual do texto selecionado (wxTextCtrl::GetStyle() não é suportado em todas as plataformas, testei no Linux e não funcionou). Após obter a formatação, iremos utilizá-la em wxGetFontFromUser() para inicializar os valores da janela, assim, sempre a janela de formatação for aberta, ela estará configurada com a formatação atual.
Em seguida, wxGetFontFromUser() retorna a nova formatação e podemos aplicá-la ao texto selecionado.
Agora devemos criar um botão na barra de ferramentas para este método. Vamos adicionar uma ID para este botão:
// IDs
enum
{
ID_TBAR_NEW,
ID_TBAR_LOAD,
ID_TBAR_SAVE,
ID_TBAR_FORMAT, // Este foi adicionado
ID_TBAR_ABOUT
};
E criamos o novo botão no construtor de MeuFrame:
tbar->AddTool(ID_TBAR_FORMAT, wxString(wxT("Formatar")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));
Pronto! Está feito. :)

Próximo passo
O editor de textos pára por aqui. Estou querendo falar sobre sockets no próximo post, mas precisarei elaborar um texto maior, pois tem bastante coisa pra explicar. Se alguém quiser aprender algo específico do wxWidgets, postem nos comentários. Assim vocês me ajudam a escolher o próximo assunto. :)
Como sempre faço, o código-fonte completo está abaixo:
/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Um editor de textos
*
* O objetivo deste código-fonte é demonstrar diversas classes
* ensinadas no curso de wxWidgets do blog "A Casa de Just".
*
* As aulas do curso de wxWidgets podem ser encontradas em forma
* de posts no blog: http://jpjust.blogspot.com
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 07 de fevereiro de 2007, 20:24, Ilhéus, BA, Brasil.
*/
#include <wx/wx.h>
#include <wx/fontdlg.h>
// IDs
enum
{
ID_TBAR_NEW,
ID_TBAR_LOAD,
ID_TBAR_SAVE,
ID_TBAR_FORMAT,
ID_TBAR_ABOUT
};
// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};
// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);
// Eventos
void OnToolBarClick(wxCommandEvent &event);
// Métodos auxiliares
void Novo(void);
void Abrir(void);
void Salvar(void);
void Formatar(void);
void Sobre(void);
DECLARE_EVENT_TABLE()
private:
// Widgets do frame
wxTextCtrl *txt_file;
wxToolBar *tbar;
wxStatusBar *stbar;
};
// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
wxInitAllImageHandlers(); // Inicia todos os hadlers de imagens do wxBitmap
MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}
// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_TOOL_RANGE(ID_TBAR_NEW, ID_TBAR_ABOUT, MeuFrame::OnToolBarClick)
END_EVENT_TABLE()
// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Editor de textos - http://jpjust.blogspot.com"))
{
// Sizer e widgets
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);
txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
// Barra de ferramentas
tbar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_TEXT);
tbar->AddTool(ID_TBAR_NEW, wxString(wxT("Novo")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));
tbar->AddTool(ID_TBAR_LOAD, wxString(wxT("Abrir")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-folder.png"), wxBITMAP_TYPE_PNG));
tbar->AddTool(ID_TBAR_SAVE, wxString(wxT("Salvar")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-cd.png"), wxBITMAP_TYPE_PNG));
tbar->AddSeparator();
tbar->AddTool(ID_TBAR_FORMAT, wxString(wxT("Formatar")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));
tbar->AddSeparator();
tbar->AddTool(ID_TBAR_ABOUT, wxString(wxT("Sobre")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-info.png"), wxBITMAP_TYPE_PNG));
tbar->Realize();
// Barra de status
stbar = new wxStatusBar(this);
stbar->SetStatusText(wxT("Sem título"));
// Posicionamento
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);
SetSizerAndFit(sizer_v);
// Insere a barra de ferramentas e a barra de status
SetToolBar(tbar);
SetStatusBar(stbar);
}
// Limpa a tela para um novo arquivo
void MeuFrame::Novo(void)
{
int msg = wxMessageBox(wxT("Deseja salvar o arquivo atual antes de criar um novo?"), \
wxT("Novo arquivo"), wxYES_NO | wxCANCEL);
if (msg == wxYES) // Salva
Salvar();
else if (msg == wxCANCEL) // Cancela a operação
return;
// Cria um novo arquivo
txt_file->Clear();
stbar->SetStatusText(wxT("Sem título"));
}
// Abre um arquivo
void MeuFrame::Abrir(void)
{
wxString Filename;
// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);
// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;
txt_file->LoadFile(Filename);
// Atualiza o nome
stbar->SetStatusText(Filename);
}
// Salva o arquivo aberto
void MeuFrame::Salvar(void)
{
wxString Filename;
// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);
// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;
txt_file->SaveFile(Filename);
// Atualiza o nome do arquivo
stbar->SetStatusText(Filename);
}
// Formatação
void MeuFrame::Formatar(void)
{
long inicio, fim;
wxTextAttr attr;
wxFont font;
// Obtém a formatação atual (não suportado em todas as plataformas)
txt_file->GetSelection(&inicio, &fim);
txt_file->GetStyle(inicio, attr);
font = attr.GetFont();
// Altera a formatação
font = wxGetFontFromUser(this, font);
attr.SetFont(font);
txt_file->SetStyle(inicio, fim, attr); // Aplica o estilo ao texto
}
// Janela "Sobre"
void MeuFrame::Sobre(void)
{
wxMessageBox(wxT("Curso de wxWidgets\n\nhttp://jpjust.blogspot.com"), wxT("Sobre"), wxICON_INFORMATION);
}
// Método para a barra de ferramentas
void MeuFrame::OnToolBarClick(wxCommandEvent &event)
{
switch (event.GetId())
{
case ID_TBAR_NEW:
Novo();
break;
case ID_TBAR_LOAD:
Abrir();
break;
case ID_TBAR_SAVE:
Salvar();
break;
case ID_TBAR_FORMAT:
Format();
break;
}
}
IMPLEMENT_APP(MeuPrograma)
segunda-feira, janeiro 29, 2007
Curso de wxWidgets, post 12: Adicionando uma barra de status
O post de hoje vai ser bem simples e rápido, iremos apenas adicionar uma barra de status ao nosso editor de textos. Essa barra de status irá informar o nome do arquivo que estamos editando.
Para a barra de status, vamos usar a classe wxStatusBar. O construtor é bem simples:
Nenhum dos parâmetros são obrigatórios, existe o construtor sem parâmetros também. Mas recomenda-se usar this como primeiro parâmetro, para associar a barra com a janela que a está contendo. E é assim que nós iremos fazer no nosso editor de textos. Na definição da classe MeuFrame, temos que adicionar a barra como um atributo em private:
No construtor de MeuFrame, iremos instanciar o objeto e definir um texto inicial para a barra de status:
O método wxStatusBar::SetStatusText() recebe dois parâmetros: o primeiro, é o texto que você irá colocar na barra, o segundo e opcional, é o número do campo da barra que irá receber o texto.
No nosso exemplo, estamos usando apenas um campo de texto, mas podem existem barras com vários. Você pode ajustar o número de campos da sua barra com o método wxStatusBar::SetFieldsCount(). Por exemplo, se quiser três campos na sua barra, use o método da seguinte forma:
E para alterar o texto do segundo campo, use:
Como temos apenas um campo em nossa barra, não precisamos especificar o número dele.
Em seguida, devemos "colar" esta barra de status na janela. Fazemos isso com o método wxFrame::SetStatusBar(), ainda no construtor:
Pronto, a barra já está criada e dentro da nossa janela. Vamos agora atualizar os métodos MeuFrame::Abrir() e MeuFrame::Salvar(), que deverão modificar o texto da barra de status.
No código do nosso editor de textos, procure as linhas:
Essas linhas modificam o nome do arquivo no nosso wxStaticText. Iremos remover essas linhas e no lugar delas, colocar:
Agora o editor de textos já está com a barra pronta. Já que não vamos mais usar o lb_filename, podemos removê-lo do construtor e da definição de MeuFrame.
Compile o novo código e veja a barra em funcionamento:

Código-fonte atualizado
O código completo e atualizado está abaixo. No novo código, eu removi o lb_filename, como mostrado neste post. Também removi btn_load e btn_save, já que agora temos a barra de ferramentas. Além disso, criei o método MeuFrame::Novo(), para criar um novo arquivo e seu respectivo botão na barra de ferramentas. Também removi a mensagem de boas-vindas. Olhe o código inteiro para ver as modificações e entendê-las.
Para a barra de status, vamos usar a classe wxStatusBar. O construtor é bem simples:
wxStatusBar(wxWindow* parent, wxWindowID id = wxID_ANY, long style = wxST_SIZEGRIP,
const wxString& name = "statusBar")
parent: A janela que vai conter a barra de status.
id: ID da barra, para os eventos.
style: Estilo da barra. Existe apenas o estilo wxST_SIZEGRIP, que exibe um "puxador" no canto
direito da barra no Windows.
name: Nome da barra.
Nenhum dos parâmetros são obrigatórios, existe o construtor sem parâmetros também. Mas recomenda-se usar this como primeiro parâmetro, para associar a barra com a janela que a está contendo. E é assim que nós iremos fazer no nosso editor de textos. Na definição da classe MeuFrame, temos que adicionar a barra como um atributo em private:
private:
wxStatusBar *stbar;
No construtor de MeuFrame, iremos instanciar o objeto e definir um texto inicial para a barra de status:
// Barra de status
stbar = new wxStatusBar(this);
stbar->SetStatusText(wxT("Sem título"));
O método wxStatusBar::SetStatusText() recebe dois parâmetros: o primeiro, é o texto que você irá colocar na barra, o segundo e opcional, é o número do campo da barra que irá receber o texto.
No nosso exemplo, estamos usando apenas um campo de texto, mas podem existem barras com vários. Você pode ajustar o número de campos da sua barra com o método wxStatusBar::SetFieldsCount(). Por exemplo, se quiser três campos na sua barra, use o método da seguinte forma:
stbar->SetFieldsCount(3);
E para alterar o texto do segundo campo, use:
stbar->SetStatusText(wxT("Campo 2"), 1);
// O primeiro campo é o zeroComo temos apenas um campo em nossa barra, não precisamos especificar o número dele.
Em seguida, devemos "colar" esta barra de status na janela. Fazemos isso com o método wxFrame::SetStatusBar(), ainda no construtor:
SetStatusBar(stbar);
Pronto, a barra já está criada e dentro da nossa janela. Vamos agora atualizar os métodos MeuFrame::Abrir() e MeuFrame::Salvar(), que deverão modificar o texto da barra de status.
No código do nosso editor de textos, procure as linhas:
lb_filename->SetLabel(Filename);
Essas linhas modificam o nome do arquivo no nosso wxStaticText. Iremos remover essas linhas e no lugar delas, colocar:
stbar->SetStatusText(Filename);
Agora o editor de textos já está com a barra pronta. Já que não vamos mais usar o lb_filename, podemos removê-lo do construtor e da definição de MeuFrame.
Compile o novo código e veja a barra em funcionamento:

Código-fonte atualizado
O código completo e atualizado está abaixo. No novo código, eu removi o lb_filename, como mostrado neste post. Também removi btn_load e btn_save, já que agora temos a barra de ferramentas. Além disso, criei o método MeuFrame::Novo(), para criar um novo arquivo e seu respectivo botão na barra de ferramentas. Também removi a mensagem de boas-vindas. Olhe o código inteiro para ver as modificações e entendê-las.
/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Um editor de textos
*
* O objetivo deste código-fonte é demonstrar diversas classes
* ensinadas no curso de wxWidgets do blog "A Casa de Just".
*
* As aulas do curso de wxWidgets podem ser encontradas em forma
* de posts no blog: http://jpjust.blogspot.com
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 29 de janeiro de 2007, 9:48, Ilhéus, BA, Brasil.
*/
#include <wx/wx.h>
#include <wx/textfile.h>
// IDs
enum
{
ID_TBAR_NEW,
ID_TBAR_LOAD,
ID_TBAR_SAVE,
ID_TBAR_ABOUT
};
// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};
// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);
// Eventos
void OnToolBarClick(wxCommandEvent &event);
// Métodos auxiliares
void Novo(void);
void Abrir(void);
void Salvar(void);
void Sobre(void);
DECLARE_EVENT_TABLE()
private:
// Widgets do frame
wxTextCtrl *txt_file;
wxToolBar *tbar;
wxStatusBar *stbar;
};
// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
wxInitAllImageHandlers(); // Inicia todos os hadlers de imagens do wxBitmap
MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}
// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_TOOL_RANGE(ID_TBAR_NEW, ID_TBAR_ABOUT, MeuFrame::OnToolBarClick)
END_EVENT_TABLE()
// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Editor de textos - http://jpjust.blogspot.com"))
{
// Sizer e widgets
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);
txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
// Barra de ferramentas
tbar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_TEXT);
tbar->AddTool(ID_TBAR_NEW, wxString(wxT("Novo")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));
tbar->AddTool(ID_TBAR_LOAD, wxString(wxT("Abrir")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-folder.png"), wxBITMAP_TYPE_PNG));
tbar->AddTool(ID_TBAR_SAVE, wxString(wxT("Salvar")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-cd.png"), wxBITMAP_TYPE_PNG));
tbar->AddSeparator();
tbar->AddTool(ID_TBAR_ABOUT, wxString(wxT("Sobre")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-info.png"), wxBITMAP_TYPE_PNG));
tbar->Realize();
// Barra de status
stbar = new wxStatusBar(this);
stbar->SetStatusText(wxT("Sem título"));
// Posicionamento
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);
SetSizerAndFit(sizer_v);
// Insere a barra de ferramentas e a barra de status
SetToolBar(tbar);
SetStatusBar(stbar);
}
// Limpa a tela para um novo arquivo
void MeuFrame::Novo(void)
{
int msg = wxMessageBox(wxT("Deseja salvar o arquivo atual antes de criar um novo?"), \
wxT("Novo arquivo"), wxYES_NO | wxCANCEL);
if (msg == wxYES) // Salva
Salvar();
else if (msg == wxCANCEL) // Cancela a operação
return;
// Cria um novo arquivo
txt_file->Clear();
stbar->SetStatusText(wxT("Sem título"));
}
// Abre um arquivo
void MeuFrame::Abrir(void)
{
wxString Filename;
// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);
// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;
txt_file->LoadFile(Filename);
// Atualiza o nome
stbar->SetStatusText(Filename);
}
// Salva o arquivo aberto
void MeuFrame::Salvar(void)
{
wxString Filename;
// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);
// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;
txt_file->SaveFile(Filename);
// Atualiza o nome do arquivo
stbar->SetStatusText(Filename);
}
// Janela "Sobre"
void MeuFrame::Sobre(void)
{
wxMessageBox(wxT("Curso de wxWidgets\n\nhttp://jpjust.blogspot.com"), wxT("Sobre"), wxICON_INFORMATION);
}
// Método para a barra de ferramentas
void MeuFrame::OnToolBarClick(wxCommandEvent &event)
{
switch (event.GetId())
{
case ID_TBAR_NEW:
Novo();
break;
case ID_TBAR_LOAD:
Abrir();
break;
case ID_TBAR_SAVE:
Salvar();
break;
case ID_TBAR_ABOUT:
Sobre();
break;
}
}
IMPLEMENT_APP(MeuPrograma)
Assinar:
Postagens (Atom)